Ex17 Seg fault when setting new entries


#1

Hi all,

I am having trouble with ex17.c in the extra credit for making the database dynamically sized. I keep getting seg faults when I try to access records after creating it.
I have changed quite a lot, so I thought I should provide the whole code, but I didn’t want to clutter up a post with 200 lines of code. I can print it here if you prefer.
I have looked at the other posts in this forum, and I have attempted to take some advice from what Zed said in this post: EX17 Dynamic Resizing of MAX_DATA Problem
I’m getting stuck on some problems however.
I am now able to run ./ex17 db.dat c without any problems. Valgrind shows that all memory is freed, and the long listing of the file is 10328 bytes, which it should be for 10 rows with max_data of 512, and two ints for conn->db->max_data and conn->db->max_rows.

However, when I try to run ./ex17 db.dat s 1 zed zed@zedshaw.com to set a new entry, or when I run ./ex17 db.dat l to list entries, I get a segfault.
In valgrind for listing, it tells me I have an invalid free. I suspect this is because in the Database_close function I am calling for it to free conn->db->rows. This call is necessary when creating the database, because I allocate that memory. When I run the program to list the db however, I am not allocating the memory, but the rows still exist because they have been written to the file. Is there a way around this? And is this the only cause of the segfault?
I’m not sure if I’m writing to the database correctly when I create it, but I cannot write row structs one by one, as fwrite() expects a pointer, not a struct.
When I run the program with set options in GDB, I have been able to print addr->set, id, name, and email in the Database_set() function. Currently when I do that, I get to line 135, if (addr->set) and I get a seg fault. GDB keeps telling me it cannot access memory at 0x52024d8, which is the same address for conn->db->rows[id] and for addr afterwards. This seems to be inconsistent, as I have been able to print this information previously.
I’m at a bit of a loss as to what is going wrong at the moment. I would not be surprised to learn that it is occurring at the time of writing the database when I create it. It is clearly writing the correct number of bytes to the file, but that is probably only because I passed the correct number to the function. It may be filling up empty space with 0s. I would also not be surprised to learn that in converting all this from stack to heap, I have messed up how the pointers are behaving and I am trying to access something that does not exist in the Database_set() function.
Sorry this is so long-winded, but I’ve been trying to solve this for a long time, and I would just like some clarity on why I keep getting so many segfaults. Let me know if you need any more information, and thank you for such a challenging exercise. This exercise has taught me more than I ever wanted to know about working with memory!


Double free or corruption - ex17.c simulation
#2

Hey, I am at ex17 too , but haven’t done the extra credit yet. Will come back with news.


#3

Did you try to compile it with clang -Wall -Werror?
clang -Wall -Werror ex17.c -o ex17 (if you want your compiled file to be named ex17 instead of a.out)
You can also include gdb in the above command:
clang -ggdb -Wall _Werror ex17.c -o ex17
Maybe you get more hints :smiley:
Yesterday I was about to pull my hair off because my ex16 script worked fine. Then I broke it. Then I removed NULL and fixed it.
Then had some stuff to do around the house.
When I came back and ran it again I had an error.
What I did was I forgot to remove the broken compiled file… :smiley:
And I got this habit of searching the error in the code I wrote, not yet used to the idea that there’s actually the compiled file too…
L.E.: I think you can solve this yourself. I think it’s great that we can ask for help here whenever we are really stuck, but also this struggling to find out what is wrong there forces us to understand what’s inside that computer and what is it trying to tell us.
So Google it till you bleed, lol.


#4

That is true. It is very annyoing sometimes to hit some broken things again and again and to tediously research the problems. But once it is done, so much is learned.


#5

And use the error messages for great good! :slight_smile:


#6

Ok, I compiled it for the first time and got 10 errors, lol.
Will update tomorrow.


#7

Thanks guys. @io_io I run Gentoo Linux so I’m using GCC, not clang, but I do use a makefile, so I don’t a.out. I tried adding -Werror and -ggdb to the makefile, but I still don’t get any compilation errors. The compiler usually doesn’t warn about illegal memory access, as it is not able to read the future, even when something is obviously going to blow up when you try to run it.
I agree, I should be able to solve this myself, but I’ve been stuck on it for a while. I think the big problem is trying to treat struct Address *rows as an array while initialising it as one big block of memory. The program is still treating the pointer as pointing to one block, but the list and set functions try to access indices within that block. I’m currently trying to write a small project which does some similar things to get some insight from another angle, but if anyone has any insight about what’s actually causing the problem, it would be very much appreciated.


#8

I’m on Pop OS (Ubuntu based) and I installed clang because I was curious.
Not yet at the extras, but will tell you how it works when I get there.