-1

When I call the print_linklist function I am getting a segmentation fault. Here is the function definition:

//will display the node in a nice string
char * term_to_string(term_t * term){
    int exp = term->exponent;
    int coef = term->coefficient;
    return ("%dx^%d", coef, exp);
}

**//will print the list using the nodde_to_string method
void print_linklist(node_t * curr){
    printf("entering print to list!!!");
    node_t * current = curr;
    while(current != NULL){
        printf("%s +", term_to_string(curr->term));
        current = current->next_node;
    }
}**

And here is the main method where it is being called:

/* This is your main file */
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"common.h"
#include"buildlinklist.h"
#include"printandcombine.h"
int main() {
    node_t * node_ptr = NULL;
    node_t * new_node_ptr=NULL;
    printf("NAME: SAMPLE OUTPUT\n");
    
    /* Build linklist */
    read_objects(&node_ptr);
    
    /* Print the link list */
    printf("Original: \n");
    print_linklist(node_ptr);
    
    /* Combine like terms in the link list and craeate a new link list */
    new_node_ptr=combine_like_terms(node_ptr);
    printf("\nCombined: : ");
    /* Print new combine linklist */
    print_linklist(new_node_ptr);
    printf("\nNAME: SAMPLE OUTPUT\n");
    free(node_ptr);
    free(new_node_ptr);
    return 0;
}

After the function is called I get "zsh: segmentation fault ./project1". I don't even get the "entering print to list!!!" to print from the print_linklist method.

GWFarrin
  • 27
  • 3
  • 1
    Have you tried using a debugger to execute your line-by-line and find your mistake? – Kitswas Jul 01 '21 at 04:37
  • So debug it. Run your program in a debugger. At a minimum it will give you the exact line of code that triggers the seg fault. That is the bare minimum debugging you should have done and should have included the resulting info in the question. – kaylum Jul 01 '21 at 04:37
  • @PalLaden I unfortunately don't know how to do that. I am working in Xcode and using gcc to compile. I am a student and extremely new to working in C. – GWFarrin Jul 01 '21 at 04:38
  • 1
    Is your compiler giving you any warnings? – Joseph Sible-Reinstate Monica Jul 01 '21 at 04:41
  • @JosephSible-ReinstateMonica None for this method. They are for the term_to_string method. But this method won't even print the test line that I put at the beginning of it to run upon function call. – GWFarrin Jul 01 '21 at 04:43
  • GW, that's because standard output is line buffered by default. Your incomplete line (no `\n`) is in the output buffer but you're crashing (see my answer as to why) before it flushes. – paxdiablo Jul 01 '21 at 04:47
  • 1
    @JosephSible: OP mentioned he *is* getting warnings for `term_to_string`, that's where I'd expect to see them since that's the thing that treats a numeric exponent as if it were a char pointer. – paxdiablo Jul 01 '21 at 04:52
  • 2
    The root of the problem here is actually a misconfigured compiler. You should never get a seg fault from this code because it should never compile. If you are using gcc, then invoke it as `-Wall -Wextra -std=c11 -pedantic-errors`. After which you get "error: return makes pointer from integer without a cast". For beginners I would even recommend to use `-Werror`. – Lundin Jul 01 '21 at 09:27

3 Answers3

5
return ("%dx^%d", coef, exp);

That's not doing what you seem to think it's doing (what I think you think it's doing is to return a string created by some sort of printf functionality).

However, the comma operator in something like a, b evaluates both a and b, but the result is b. The n-variant, like a, b, c, d, evaluates everything and returns the last one (d).

Hence you are returning exp as if it was a character pointer. It almost certainly isn't (since you're trying to printf it with %d) so, if you treat it as such, hilarity may ensue.

Well, less hilarity and more crashing/weirdness, but you get the idea :-)


You could create strings in heap memory and pass them around but it's sometimes difficult for newcomers to the language to do that safely. Instead, I would suggest simply printing the thing within the function, with something like:

void print_term(const term_t *term, const char *after){
    printf("%dx^%d%s", term->coefficient, term->exponent, after);
}

void print_linklist(node_t *curr){
    puts("entering print to list!!!");
    node_t *current = curr;
    while (current != NULL){
        print_term(curr->term, " +");
        current = current->next_node;
    }
}

You'll notice my "entering print to list" statement is subtly different to yours in that it uses puts, which appends a newline character to the end (you could do that explicitly, with \n, if you wanted to stick with printf).

Since standard output is line-buffered for terminal devices, the reason you're not seeing that is almost certainly due to the fact your code is crashing (as per this answer) before it flushes. In that case, unflushed data is likely to just disappear.

ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • 2
    In C, you can't even return an `int` from a function returning a `char*`. The compiler will give a diagnostic message pointing out the language constraint violation. If you get some binary executable despite that message, all bets of what it does are off, because it wasn't written in valid C. – Lundin Jul 01 '21 at 09:30
  • I'm not convinced that's correct, @Lundin. `C11 6.3.2.3` states that pointer-to-integer and integer-to-pointer conversion are allowed, though the results are implementation-defined. Additionally, `6.8.6.4` (return) states: `If the expression has a type different from the return type of the function in which it appears, the value is converted as if by assignment to an object having the return type of the function.` They seem to allow for this case explicitly. And a diagnostic message doesn't have to be an error, it's simply one of a set of implementation-defined messages (including warnings). – paxdiablo Jul 01 '21 at 09:54
  • 1
    The relevant part is 6.8.6.4 which in turn points at the rules of simple assignment, 6.5.16. Which don't allow an implicit conversion. Parameter passing & variable initialization follow exactly the same rules too. For details see [“Pointer from integer/integer from pointer without a cast” issues](https://stackoverflow.com/questions/52186834/pointer-from-integer-integer-from-pointer-without-a-cast-issues). – Lundin Jul 01 '21 at 10:10
  • @Lundin: okay, I see now, it's actually the constraints in 6.5.16.1, which don't allow for `charPtrVar = intVar` (as assignment is the basic behavioural model for returning a value), even though explicit casts appear to be allowed. Thanks. – paxdiablo Jul 01 '21 at 12:34
  • Yep, soon as you do an explicit cast the 6.3.2.3 that you mention is what applies and the resulting type of the cast is what simple assignment gets as right operand. – Lundin Jul 01 '21 at 13:40
0

I don't even get the "entering print to list!!!" to print from the print_linklist method.

printf doesn't cause anything to be printed to the screen. It just copies a string into a buffer to be printed at some later time. If you want to force the buffer to be printed, you can call fflush. As mentioned in comments, if stdout is directed to an interactive device, including a \n in the output string will generally also cause the buffer to be flushed to the actual output device.

After the function is called I get "zsh: segmentation fault ./project1".

This probably happens in term_to_string if you call it with an invalid pointer argument, when it tries to dereference its argument.

The Photon
  • 1,242
  • 1
  • 9
  • 12
  • Photon, just FYI, standard output is line buffered if it can be determined to be an interactive device, fully buffered otherwise. So, if you're just running the code from a terminal, a newline should do the trick. – paxdiablo Jul 01 '21 at 04:55
  • Having said that, when I'm debugging crashes, I often use `printf(something); fflush(stdout); fsync(fileno(stdout)); system("sync");` just because I'm paranoid :-) – paxdiablo Jul 01 '21 at 05:07
0

There could be a number of reasons you are getting a segmentation fault but trying to print the list is not one of them. If your read_objects() declaration is like this read_objects(node_t * curr) then you shouldn't pass as an argument the address of the pointer

read_objects(&node_ptr);

This should be read_objects(node_ptr);

Also, if you want to iterate through the list and print it you should create a pointer to the head of the list in the main() function node_t *head = NULL; and pass it as a parameter in the print_linklist(head);.

After that, make *current point at the head of the list node_t * current = head;.

That way you are starting printing the nodes from the start. You should also check if the list is empty.

XBis
  • 1
  • 1