user1697083
user1697083

Reputation:

Segmentation fault when trying to access a struct array

As part of an assignment, I have to deal with three structs. There is some larger table within a file, FileHeader, that is made up of SectionHeader structs. Hdr is made up of an array of these structs laid out in contiguous memory. As a result, I should be able to access the array by typecasting the location of the table in memory.

typedef struct {
    unsigned int offset; // offset in bytes from start of file to section headers
    unsigned short headers; // count of section headers in table
} FileHeader;

typedef struct {
    unsigned int name;
    unsigned int type;        
} SectionHeader;

I am supposed to: Use the offset and headers fields from the FileHeader (hdr) to identify the location and length of the section header table. I have assumed the start of the file is &hdr.

So I did this, but it is giving me a seg-fault. What is the proper way to access this array?

    int header_location = hdr.offset;
    int header_length = hdr.headers;

    SectionHeader *sec_hdrs = (SectionHeader *) &hdr + header_location;

    SectionHeader sec_hdr;

    for (int i = 0; i < header_length; i++) {

            sec_hdr = sec_hdrs[i];
            if (sec_hdr.type == SHT_SYMTAB) break;
    }

Upvotes: 0

Views: 663

Answers (3)

Toby Liu
Toby Liu

Reputation: 1267

Here is a visualization of the memory with an initial offset followed by SectionHeader's placed in contiguous memory.

header_location | sizeof(SectionHeader)| sizeof(SectionHeader) | sizeof(SectionHeader)

vijairaj makes a very valid point about a possible bug in your code.

Your original code &hdr + header_location would offset the pointer by sizeof(hdr) * header_location which is not your intention.

This is a valid diagnosis and you should investigate how pointer arithmetic works. We increment the address by the size of its type. Once you are sure that *sec_hdrs is pointing to the correct place, rerun your program. If the segfault persists, try my next piece of debugging advice.

Yes, on other questions here, I have seen that you might have to malloc first. But I do not understand why that is necessary if you have a pointer to the array if you know that it is in contiguous memory, and also how to do this.

Just because we know something is in contiguous memory does not mean it is safe from being overwritten or reused by our program. That is the point of malloc - to protect certain blocks of memory from being overwritten. If you access unallocated memory, you run the risk of accessing sensitive data, overwriting program-dependent data, or storing data that will get overwritten. This is why a segfault will occur and this is why you need to malloc.

Ensure that you malloc enough space:

 malloc(header_location + header_length * sizeof(SectionHeader))

This line of code is saying, "Please allocate contiguous memory for one offset and n SectionHeader's". The malloc call will return a pointer to the start of that memory block (&hdr) and then you may access anything within that block of memory.

Perhaps include the code that is providing you with &hdr? Hope this is helpful!

Upvotes: 0

haccks
haccks

Reputation: 106012

You declared sec_hdrs as a pointer to SectionHeader. It is not an array and it can't be indexed. Your compiler should raise a warning.

Try this:

SectionHeader hdrs[header_length]
int header_location = hdrs[0].offset;
int header_length = hdrs[0].headers;

SectionHeader *sec_hdrs = hdrs + header_location;

SectionHeader sec_hdr;

for (int i = 0; i < header_length; i++) {
     sec_hdr = sec_hdrs[i];
     if (sec_hdr.type == SHT_SYMTAB) break;
}

Upvotes: 0

vijairaj
vijairaj

Reputation: 320

Try this: ElfSectionHeader *sec_hdrs = (ElfSectionHeader *)((unsigned char *) &hdr + header_location);

Your orinal code &hdr + header_location would offset the pointer by sizeof(hdr) * header_location which is not your intention.

Upvotes: 2

Related Questions