0

I'm writing an assembler project and encountered a problem when I tried to allocate memory for a struct.

Basically, the malloc itself causes a segmentation fault, it doesn't even return a value.

Worth to mention, on both VSCode on mac and CLion on Windows it works perfectly fine, but on Ubuntu 16 (The environment we need to work with) it provokes an error.

Here's the struct's definition:

typedef struct symbol
{
char *labelName;
char *entExtName;
int labelType;
int address;
short int value; /* ADDED - for data types. Else - set to NULL*/
int operation; 
int external;
struct symbol * next;
} symbol;

Here's the addSymbol function:

void addSymbol(char *label, int address, int external, int op, int line)
{
symbol *pSymbol;    /* Symbol pointer */
pSymbol = (symbol*)malloc(sizeof(symbol)+1); /* --- ERROR INVOKED HERE --- */

checkMalloc(pSymbol); 

symbolExistence(label, line);  /* If the symbol already exists in list */

pSymbol->labelName = label; /* Copies the name */
pSymbol->external = external;
pSymbol->address = address;   /* Copies the value of DC */
pSymbol->operation = op; /* Copies operation */
pSymbol->next = NULL; /* Set next to NULL */

if (head_symbol == NULL) /* If the list is empty */
{
    head_symbol = pSymbol; /* Set the head to point at pSymbol */
}

else /* If the list is not empty, find the last node and add the new node */
{
    symbol *ptrSymbol = head_symbol; 
    while (ptrSymbol->next != NULL)
        ptrSymbol = ptrSymbol->next;

    ptrSymbol->next = pSymbol; /*set last node point as pSymbol*/
    }
}

EDIT

I tried to change and use calloc instead of malloc, now in an earlier spot in the code which is similar (a different struct) I get this error:

*** Error in `./main': corrupted size vs. prev_size: 0x09db65d8 ***
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(+0x67377)[0xb75ca377]
/lib/i386-linux-gnu/libc.so.6(+0x6d2f7)[0xb75d02f7]
/lib/i386-linux-gnu/libc.so.6(+0x6f979)[0xb75d2979]
/lib/i386-linux-gnu/libc.so.6(__libc_calloc+0xb8)[0xb75d48c8]
./main[0x8049155]
./main[0x804af8f]
./main[0x804c1de]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf7)[0xb757b637]
./main[0x8048951]
======= Memory map: ========
08048000-0804e000 r-xp 00000000 08:02 409071     /home/user/Desktop/Project/20.8 C-Lab-Project/main
0804f000-08050000 r--p 00006000 08:02 409071     /home/user/Desktop/Project/20.8 C-Lab-Project/main
08050000-08051000 rw-p 00007000 08:02 409071     /home/user/Desktop/Project/20.8 C-Lab-Project/main
09db5000-09dd6000 rw-p 00000000 00:00 0          [heap]
b7400000-b7421000 rw-p 00000000 00:00 0 
b7421000-b7500000 ---p 00000000 00:00 0 
b752f000-b754b000 r-xp 00000000 08:02 931606     /lib/i386-linux-gnu/libgcc_s.so.1
b754b000-b754c000 rw-p 0001b000 08:02 931606     /lib/i386-linux-gnu/libgcc_s.so.1
b7562000-b7563000 rw-p 00000000 00:00 0 
b7563000-b7713000 r-xp 00000000 08:02 933356     /lib/i386-linux-gnu/libc-2.23.so
b7713000-b7715000 r--p 001af000 08:02 933356     /lib/i386-linux-gnu/libc-2.23.so
b7715000-b7716000 rw-p 001b1000 08:02 933356     /lib/i386-linux-gnu/libc-2.23.so
b7716000-b7719000 rw-p 00000000 00:00 0 
b7719000-b776c000 r-xp 00000000 08:02 933352     /lib/i386-linux-gnu/libm-2.23.so
b776c000-b776d000 r--p 00052000 08:02 933352     /lib/i386-linux-gnu/libm-2.23.so
b776d000-b776e000 rw-p 00053000 08:02 933352     /lib/i386-linux-gnu/libm-2.23.so
b7783000-b7786000 rw-p 00000000 00:00 0 
b7786000-b7788000 r--p 00000000 00:00 0          [vvar]
b7788000-b7789000 r-xp 00000000 00:00 0          [vdso]
b7789000-b77ab000 r-xp 00000000 08:02 931813     /lib/i386-linux-gnu/ld-2.23.so
b77ab000-b77ac000 rw-p 00000000 00:00 0 
b77ac000-b77ad000 r--p 00022000 08:02 931813     /lib/i386-linux-gnu/ld-2.23.so
b77ad000-b77ae000 rw-p 00023000 08:02 931813     /lib/i386-linux-gnu/ld-2.23.so
bff16000-bff37000 rw-p 00000000 00:00 0          [stack]
Aborted (core dumped)

Is there a way I could use this information to find the corruption?

Any help would be greatly appreciated.

Gibieyal
  • 5
  • 2
  • When you debug and reach that line, what is value is malloc specifically being called with? – JohnFilleau Aug 21 '22 at 16:59
  • You probably don't need `+1` in `malloc` call... we usually use that only for strings because of terminating `\0`. – Overjoyed Aug 21 '22 at 17:01
  • 2
    Note that the comment for `pSymbol->labelName = label` is *misleading*. The assignment doesn't copy the string itself, only the pointer to the first character of the string. If you really want to copy the string itself use the commonly available `strdup` function, or create such a function yourself. – Some programmer dude Aug 21 '22 at 17:01
  • 2
    Also note that `malloc` doesn't initialize the memory it allocates. That means the members of the structure you don't initialize (like `entExtName`) will have *indeterminate* values. Attempting to dereference `entExtName` will lead to *undefined behavior*. – Some programmer dude Aug 21 '22 at 17:02
  • Sounds like the bug is elsewhere in code (heap corruption caused by UB) and it is only showing up during this particular malloc call. – JohnFilleau Aug 21 '22 at 17:03
  • Also, and a possible cause for undefined behavior and crashes when dealing with `malloc`, [in C you should not cast the result of `malloc`](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc/605858). – Some programmer dude Aug 21 '22 at 17:03
  • 1
    Segmentation faults often do not occur at the same time as their root cause, but later. It is almost certain that you have corrupted the heap in your program at some point earlier in your program. – Avi Berger Aug 21 '22 at 17:03
  • On a totally unrelated note, what does `symbolExistence` do? Shouldn't the `addSymbol` return if the symbol already exist? And wouldn't it be smarter to do that check before you call `malloc`? – Some programmer dude Aug 21 '22 at 17:05
  • I also recommend that you keep a pointer to the tail of the list, to make it easier to insert at the end. Either that, or treat the list as a stack and insert at the head. – Some programmer dude Aug 21 '22 at 17:06
  • I recommend not to use a linked list. It is a wrong data structure for almost anything. – n. m. could be an AI Aug 21 '22 at 17:28
  • Thank you for all the answers. I just edited the post and switched to calloc, that invoked a different error earlier in the code with a memory map. Is there any way I could use that information to find the corruption? Thanks! – Gibieyal Aug 21 '22 at 17:41
  • If you had more than one list, you would need a different AddSymbol routine. Better to pass a pointer to `head_symbol` than use a global. – stark Aug 21 '22 at 17:47
  • Yes I have several lists of different structs, all of them are quite similar and have their own dedicated CRUD functions. – Gibieyal Aug 21 '22 at 17:55
  • 1
    run it under valgrind – pm100 Aug 21 '22 at 17:58
  • Build and link with `-g -fsanitize=address,undefined`, then run in a debugger to catch crashes and locate when and where in your code they happen. – Some programmer dude Aug 22 '22 at 05:17

1 Answers1

1

When malloc generates an exception, it usually means that you have overwritten and corrupted memory (e.g. gone beyond the bounds of an array or allocated memory). This could be due to any code anywhere in your codebase, so it could be something unrelated to the code you present. You also have not presented all the code, or are presenting code that does not compile.

Having said that, I can see some problems with regards to initialised memory. You must remember that malloc does not initialise the allocated memory. I see labelType and entExtName are not initialised. This might be related to your problem.

If you want to allocate and clear the memory you should use calloc instead of malloc.

But like I said, a crash in malloc means that something went wrong somewhere else and corrupted the hidden data the memory allocation library used to manage memory. This can be quite difficult to track down.

You can use something like BoundsChecker to try to catch your issue. You can also call a diagnostic function to check the sanity of the heap allocator, if available in your development environment, and use it by placing it at strategic points to narrow it down.

It is good practice to add asserts to your code to try and catch problems as early as possible when they occur.

Dino Dini
  • 433
  • 3
  • 6
  • 1
    Thanks for the descriptive answer @Dino Dini, at the end it was an activation of strcpy to a pointer that didn't have enough memory to hold the copied string. I just realized that the C standard library can be dangerous and that I should always write my own tests and insert conditions. Thanks again! – Gibieyal Aug 22 '22 at 08:18