0

I want to dynamically allocate only a portion of a character array.

So part of an array of size 100 is concrete. Say 10 is permanent memory, the other 90 is dynamic memory.

I made some attempt to read character by character until I decided to give up and take a shortcut idea I thought would work. However I end up getting an error that is

incorrect checksum for freed object - object was probably modified after being freed

I use this method in a while loop in main and I pretty much free everything after the while loop processes. Because, I have the declaration outside of the while loop. I wanted to read an object in a while loop session since these objects end up being added into a list of objects. However the scope of the while loop causes segmentation problems, it cannot remember anything about the object. (I digress).

Here is my attempt.

Object* read(char* str)
{
    Object* object = (Object*)malloc(sizeof(*object));
    object->identity[0] = 0;
    int capacity = (100 + 1) - (10);
    object->name = (char*)malloc(capacity * sizeof(*object->name));
    object->value = 0.0;

    int length = strlen(str);
    if (length > capacity)
        object->name = (char*)realloc(object->name, (capacity * 2) * sizeof(*object->name));

    int arguments = sscanf(str, "%" STRING_SPACE "s %lf %[^\n]s",
        object->identity,
        &object->value,
        object->name);

    if (arguments == MATCHER) {
        return object;
    } else {
        return NULL;
    }

    return object;
}

In this case, an object has a variable sized name but a fixed amount of space allocated for its identity.

I tried something else with sscanf but realized it will never work because I read the string too late to assign memory to name. See;

/*
int len = 0;
for (char* itemObserve = item->name; *itemObserve; itemObserve++) {
    if (len == sizeof(item->name)) {
        capacity *= MULTIPLIER;
        item->name = (char*)realloc(item->name, capacity * sizeof(*item->name));
    }
    len++;
}
*/

Here is the code in main, everything undefined is probably irrelevant to the bug:

int main()
{
    FILE* stream;
    Object* object;
    ObjectList* list = initList();

    while (true) {
        char* line;
        char cmd[15] = {0};
        char* arg;
        char* rest;

        printf("> ");
        line = getline(stdin);

        arg = (char*)malloc(35 * sizeof(*arg));
        rest = (char*)malloc(35 * sizeof(*rest));
        int arguments = sscanf(line, "%s %s %[^\n]", cmd, arg, rest);
        free(line);
        line = NULL;

        printf("\n");

        if (strcmp(cmd, "add") == 0) {
            arg = (char*)realloc(arg, (35 * 2) * sizeof(*arg));
            sprintf(arg, "%s %s", arg, rest);
            if ((object = read(arg)) == NULL) {
                continue;
            }
            objectListAdd(list, object);
        } else {
            free(rest);
            free(arg);
            exit(EXIT_SUCCESS);
        }
        free(rest);
        free(arg);
    }
    freeObject(object);
    freeObjectList(list);
    return EXIT_SUCCESS;
}

Separate getline function in main file

char* getline(FILE* stream)
{
    int capacity = LINE_MAX + 1;
    char* buffer = (char*)malloc(capacity * sizeof(*buffer));
    int len = 0;
    int ch;
    while ((ch = fgetc(stream)) != '\n' && (ch != EOF)) {
        if (len == capacity) {
            capacity *= MULTIPLIER;
            buffer = (char*)realloc(buffer, capacity * sizeof(*buffer));
        }
        buffer[len++] = ch;
    }
    if (ch == EOF) {
        return NULL;
    }
    buffer[len] = '\0';
    if (buffer == NULL)
        return NULL;
    return buffer;
}

There are other conditionals which work as a kind of command switch but they are irrelevant to the errors my program is exhibiting. This much I have narrowed the problem down to.

compolo
  • 9
  • 5
  • I don't see the use of `realloc` here, since you could just as well pass the correct size to the initial `malloc` call. – Some programmer dude Oct 27 '17 at 00:28
  • 2
    Also please [read about how to ask good questions](http://stackoverflow.com/help/how-to-ask) and show us a [Minimal, Complete, and Verifiable Example](http://stackoverflow.com/help/mcve). – Some programmer dude Oct 27 '17 at 00:29
  • 1
    Lastly there is no [`scanf`](http://en.cppreference.com/w/c/io/fscanf) format `"%[..]s"`, it's just `"%[...]"`, without the `"s"`. Unless your input actually *ends* with a literal `"s"`. Also take some time to read [Do I cast the result of malloc?](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc). And *never* reassign to the same pointer you pass as argument to `realloc`. – Some programmer dude Oct 27 '17 at 00:30
  • You can't have a single C array that is stored in two different parts of memory; from your description it sounds like you tried to do that. – David Grayson Oct 27 '17 at 00:31
  • Oh and what happens if `length >= (capacity * 2)`? – Some programmer dude Oct 27 '17 at 00:35
  • What is the definition of `Object`? – Daniel H Oct 27 '17 at 00:41
  • Object is pretty much everything there, its got a `char* name`, `char identity[MAX]` and `double value`. – compolo Oct 27 '17 at 00:56
  • @Someprogrammerdude so where would I reallocate to if I need my `object->name` to receive it? – compolo Oct 27 '17 at 00:57
  • Why don't you just check if `length > capacity`, and if true do e.g. `capacity *= 2;` and *then* call `malloc`. No `realloc` needed at all. – Some programmer dude Oct 27 '17 at 01:03
  • because then if length is less than capacity, no space will be allocated for name at all. – compolo Oct 27 '17 at 01:05
  • okay I guess conditional, but I still have the error "malloc: *** error for object 0x7ff535402bc8: incorrect checksum for freed object - object was probably modified after being freed." – compolo Oct 27 '17 at 01:07
  • Yes it will because you still have the original value of `capacity`. See e g [this gist for an example](https://gist.github.com/pileon/40305e3fd8277e9d396bb442de63ea26). – Some programmer dude Oct 27 '17 at 01:09
  • As for your crash you still haven't shown us a [Minimal, Complete, and Verifiable Example](http://stackoverflow.com/help/mcve). How do you call this function? What is `str` and what does it point to? How is the memory pointed to by `str` initialized? How do you use the memory of `str`, `object`, `object->name` or `object->identity` once the function returns? You do have some out-of-bounds error, but it doesn't have to be in the function you show. Have you tried running in a debugger to catch the crash in action? Where does it happen? – Some programmer dude Oct 27 '17 at 01:12
  • Perhaps you should take some time to read [How to debug small programs](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/) by Eric Lippert, and learn how to use a debugger? – Some programmer dude Oct 27 '17 at 01:13
  • The program is fairly medium size, I will get a verifiable example real quick – compolo Oct 27 '17 at 01:20
  • Here is the verifiable example. There are some preprocessor constants that you can infer are some integer. – compolo Oct 27 '17 at 01:30
  • @Someprogrammerdude have you any thoughts – compolo Oct 27 '17 at 01:45

0 Answers0