2

I encountered a problem which after expanding memory with realloc(), Segmentation fault reached when it try to reach specific memory number. 135,126th char address to be exact.

But, that mark never a problem if I allocate memory with malloc() bigger in the first place.

Here is my experiment with C that run on linux AMD64 compiled with gcc:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SECT_SIZE 25
#define SECT_EXTEND_SIZE 100
#define MAX_SECT_TEST 18000

void extend_memory(char *c_memory, int *i_current_sect_size){

    char *c_temp = realloc(c_memory, sizeof(char) * SECT_SIZE * (*i_current_sect_size + SECT_EXTEND_SIZE));
    if(c_temp == NULL){
        printf("realloc failed upon %d + %d\n", *i_current_sect_size, SECT_EXTEND_SIZE);
        exit(EXIT_FAILURE);
    }
    else{
        c_memory = c_temp;
        *i_current_sect_size += SECT_EXTEND_SIZE;
        printf("realloc success\n");
    }
}

int main(int argc, char *argv[]){

    //INITIALIZATION
    int i_current_sect_size;

    char *c_memory = (char *) malloc( sizeof(char) * SECT_SIZE * SECT_EXTEND_SIZE);
    if(c_memory == NULL){
        printf("c_memory malloc failed\n");
        exit(EXIT_FAILURE);
    } 
    else
        i_current_sect_size = SECT_EXTEND_SIZE;

    memcpy(c_memory, "123456789012345", SECT_SIZE); //fill up 0th sector.
    //INITIALIZATION FINISHED


    for(int a = 0; a < MAX_SECT_TEST; a++){ //fill dummy data foreach sectors 
        if(a + 1 == i_current_sect_size)
            extend_memory(c_memory, &i_current_sect_size);

        memcpy(&c_memory[SECT_SIZE * a], &c_memory[SECT_SIZE * (a+1)], SECT_SIZE);
        printf("success %d\n", a);
    }
    return EXIT_SUCCESS;
}

In simple words, this program would repeatedly copy previous SECT value into next SECT as counter a increase. Upon reaching maximum allocated address, it would expand memory allocation using realloc() by SECT_EXTEND_SIZE and continue doing its job. This process done when MAX_SECT_TEST reached.

I ran the program with SECT_SIZE equal to 9, 16, 25; All variations seems to fall into Segmentation Fault as it try to copy into SECT 15015, 8446, 5405 respectively.

9 x 15015 = 135,135

16 x 8446 = 135,136

25 x 5405 = 135,125

Why (135,125-135,136)th char become a limit? I have a 8GB memory by the way. I'm pretty sure the actual limit should way bigger than that.

15
  • memcpy(c_memory, "123456789012345", SECT_SIZE); reads out of bounds (SECT_SIZE is 25) Commented Mar 11, 2016 at 22:15
  • Your extend_memory is essentially a wrapper for realloc. Why did you design its interface to be different from realloc? Why aren't you returning the new pointer value, like realloc does? Commented Mar 11, 2016 at 22:25
  • @M.M thanks dude. realloc(*c_memory, sizeof(char) * SECT_SIZE * (*i_current_sect_size + SECT_EXTEND_SIZE)); need to changed as well besides two lines you corrected. Commented Mar 11, 2016 at 22:26
  • @AnT To avoid realloc() failure, I guess, as suggested in other realloc() related questions. Commented Mar 11, 2016 at 22:34
  • @Shaziq: But you have already properly taken care of any possible realloc failures inside extend_memory (which is probably one of the reasons your extend_memory even exists). Now, once you've taken care of this issue, why wouldn't you keep the external interface unchanged? I mean, one big problem with the code is that you do not properly return the result to the calling code. You can fix it by going the ** route (as suggested in the answers), or you can simply literally return it from the function. The latter looks more elegant to me. Commented Mar 11, 2016 at 22:54

2 Answers 2

3
void extend_memory(char *c_memory, int *i_current_sect_size){
        ...
        c_memory = c_temp;

is effectively a noop and caller will not see the changed c_memory.

You will need to use an argument like char **c_memory and work with *c_memory within the function.

Sign up to request clarification or add additional context in comments.

2 Comments

Either that, or make extend_memory return the new pointer, just like realloc does.
true; but because size is also adjusted and returned in a by-reference argument it might be more consistent to keep it as a parameter. Alternatively, a struct buffer { void *mem; size_t len }; can be declared and used.
1

If you want a function to update a pointer value, you must pass a pointer to the pointer:

extend_memory(&c_memory, &i_current_sect_size);

and update your function as

void extend_memory(char **c_memory, int *i_current_sect_size){
...
  char *c_temp = realloc(*c_memory, sizeof(char) * SECT_SIZE * (*i_current_sect_size + SECT_EXTEND_SIZE));
...
  *c_memory = c_temp;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.