2

I'm working on a fairly involved c program that is using a linked list of structures. There is a global variable declared at the top of one of my .c files (queue_head). This variable is now getting overwritten mysteriously, which causes seg faults.

Is there some way to find out the layout of my variables in memory. My best guess as to the cause is that something is writing past the end of it's memory and overwriting the queue_head memory location.

To test that I reversed the positions of queue_head and queue_tail in my source file, and the next time I ran the program, queue_tail was getting corrupted but queue_head was fine.

Of course it could be an errant pointer, but my belief is that it's something behind it in memory getting written to past it's memory allocation.

Is there a way to see how c maps out the variables short of disassembly?

mikekehrli
  • 332
  • 3
  • 10
  • This might help you - [Dynamic Code Analysis](https://stackoverflow.com/questions/49937/what-is-dynamic-code-analysis). – H.S. Feb 06 '18 at 10:20

2 Answers2

1

From most compilers (or more likely linkers), you can generate a .map file, which will list all global variables and functions.

You don't mention which compiler you use, but for gcc this will answer your question.

Basically, add this to your gcc line:

 -Xlinker -Map=output.map 
Neil
  • 11,059
  • 3
  • 31
  • 56
  • I believe, OP is asking for a way to get memory layout of variables at runtime. – H.S. Feb 06 '18 at 09:43
  • Actually, this is what I was looking for. I remembered something like map files from my early days of c programming. I'm not getting them now, but didn't know about the option for it. And I am using gcc. I upvoted both answers as both were applicable to the problem. This one best answers what I specifically asked. – mikekehrli Feb 06 '18 at 22:22
1

Variables are generally laid out in order of appearance in file, but if program has several files, then it's harder to predict. You can print their addresses to find possible offender:

printf("%p %p\n", &queue_head, &fishy_var);

But what's good in finding previous variable? It might well happen that broken code doesn't reference it directly.

A better approach is to use debugger. For example if you can run program in gdb, then you can use watchpoint to break at location where memory gets corrupted: watch queue_head. After this program will break every time value of queue_head changes, including legitimate uses. To isolate legitimate uses add dummy pointer variable just before queue_head and watch it:

void *fishy_var;
queue *queue_head;

And then in gdb:

break main
run
watch fishy_var
continue

This should lead right to the offending code.

Note, that you'd better put printf I showed earlier at the start of main, to 1. make sure variables are consecutive in memory and 2. make sure compiler doesn't optimize away unused fishy_var.

Uprooted
  • 941
  • 8
  • 21
  • Yes, I see what you are saying. I messed with it some more last night and put a few more variables in that same location in the file. I was able to get all of the offending overwrites into some bogus ints I added and then could read them. There is string data there, which is helping to isolate the code. Won't be able to work on it again until later, but I'm starting to get an inkling of where the error is. – mikekehrli Feb 06 '18 at 22:20
  • 1
    Thanks again. I made this the selected answer because it led to solution. I haven't used gdb before. This was a great primer. For others that come here, I'll just add some points that I needed to make it work. Add CFLAGS += -g to the Makefile so the executable will have the debug info in it. My executable required args to reproduce the problem, and for that you run gdb --args ... Finally, since my program was breaking in the middle of strcpy each time, enter bt or backtrace to find the line in my executable to fix. That listed the call stack with the exact line. – mikekehrli Feb 07 '18 at 08:16