0

I'll be honest, I'm a complete novice at c. Thus, things like malloc and realloc are alien concepts. I think I have the basics down, but I just can't quite get there 100%.

while (int args = scanf("%s", string)) {
    if (args < 0) break;
    count++;

    if (array == NULL) {
        array = (char *) malloc(strlen(string));

        if (array == NULL) {
            printf("Error allocating memory");
            exit(1);
        }
    } else {
        printf("%s %d\n", string, strlen(string));
        array = (char *) realloc(array, (sizeof(array) + strlen(string) + 1));

        if (array == NULL) {
            printf("Error allocating memory");
            free(array);
            exit(1);
        }

        printf("%lu\n", sizeof(array));
    }

    strcpy(&array[count - 1], string);
}

It's reading from terminal - cat file | ./program and is just a bunch of words of arbitrary length. I'm trying to get them all into an array (array).

Edit: I should mentino that I'm apparently trying to access memory I didn't allocated: malloc: *** error for object 0x7fe9e04039a0: incorrect checksum for freed object - object was probably modified after being freed. *** set a breakpoint in malloc_error_break to debug Segmentation fault: 11

Tyler Sebastian
  • 9,067
  • 6
  • 39
  • 62
  • `while (int args = scanf("%s", string))` does this really compile on your system? – ouah Sep 24 '13 at 21:12
  • yeah, how would you recommend doing that? – Tyler Sebastian Sep 24 '13 at 21:18
  • 1
    I would first recommend to use a C compiler to compile C, you are probably using a C++ compiler. – ouah Sep 24 '13 at 21:21
  • thanks, fixed it to work with gcc instead of g++ - I didn't even realize my editor was using it. – Tyler Sebastian Sep 24 '13 at 21:24
  • Showing the declarations of `string` and `array` would help...this (`array = (char *) malloc(strlen(string));`) is probably wrong; most likely it should be `array = malloc(sizeof(*array));` which avoids me having to know the type of `array` and still gets the answer right. If you really are allocating a `char *`, then you almost certainly need `strlen(string)+1` to allow for the null termination byte. Your code doesn't look wholly consistent. If you need an array of strings, you need both an array of characters pointers, and the pointers to each string: `char **array = 0;` but… – Jonathan Leffler Sep 24 '13 at 21:46
  • char * array; I don't actually initialize it to anything until the if (array == null) block. and thank for pointing out the null terminator - that was a mistake on my part. – Tyler Sebastian Sep 24 '13 at 22:10

2 Answers2

2

Looks like you don't understand what pointers, strings and char*s are in C. For example, here is some description.

Here are main problems:

  1. char* is not a string type. It's pointer to a place in memory, where string data lies char-by-char and terminates with char '\0' (null terminator)
  2. Thus, strcpy just copies a bunch of chars from one place (string variable) to another. In your case, it copies them to array, starting with element count-1. So, if you read a string longer than 1 char, you lost the data. What you probably want to do is sum lengths of all preceding strings and write starting with this place.
  3. The remaining problem is consequence: you don't allocate space for null terminator during the first iteration (which causes strcpy to access non-allocated memory and probably leads to the message you see after program's termination).
yeputons
  • 8,478
  • 34
  • 67
  • In fact, there is no string type in C, which you can freely allocate, concatenate and do different stuff as you do with String in Java or str in Python. Strings here are arrays of chars and all you can do is limited by standard library functions and pointers arithmetic. – yeputons Sep 24 '13 at 21:36
  • to sum the lengths of all preceding strings, is that something like `for (i = 0; i < count - 1; i++) len = strlen(array[i])` and then to write at that location is it `strcpy(&array + len, string)` – Tyler Sebastian Sep 24 '13 at 21:39
  • Nope. char* is an array of chars. If you want to write several strings to it, you can do this only by reading them one-to-one, splitting them by, for example, null chars. Like this: string\0other\0onemore\0. And the beginnings of strings will be on array[0], array[len1+1] and so on. – yeputons Sep 24 '13 at 21:46
  • But there is one more way: make an array of char*. This will have type 'char**' (pointer to pointer to char). After that, you add one element to this array on each iteration. Also you allocare extra array for this particular string on each iteration, consisting of strlen+1 chars. Then you copy data from your buffer the the last array and finally store its address to your first array, which stores pointers to all strings you read. – yeputons Sep 24 '13 at 21:47
  • 1
    There are _strings_ in C, though not a string type. In C: "a _string_ is a contiguous sequence of characters terminated by and including the first null character". In C there are _pointers to a string_. "A _pointer to a string_ is a pointer to its initial (lowest addressed) character." C11 7.1.1 1 – chux - Reinstate Monica Sep 24 '13 at 22:09
  • @yeputons thank you, this response helped me more than anything. I ended up re-evaluating and going with char ** array. Again, thanks. – Tyler Sebastian Sep 24 '13 at 22:32
1

To simplify the process, I ended up going with a char ** array instead of a char * array. For each iteration of my while loop (which, by the way, is now while (scanf("%s", string) > 0) to comply with gcc standards (I had originally compiled with g++)), I realloc using count x sizeof(char *) and then I can array[count - 1] = (char *) malloc(sizeof(string + 1) finally, strcpy(array[count - 1], string)

Tyler Sebastian
  • 9,067
  • 6
  • 39
  • 62