Realloc и strcpy - PullRequest
       35

Realloc и strcpy

0 голосов
/ 21 декабря 2011

Мой код выдает ошибку segfault: чего я не понимаю, отладчик говорит, что ошибка возникает из-за вывода значения из сохраненного_

char *stored_ = NULL;
char testMessage[15];

//strcpy(stored_, testMessage);

for (int a = 0;a < 10; a++)
{
    sprintf(testMessage,"Message::%i\n",a);
    printf("string is:%s;length is %i\n",testMessage,strlen(testMessage));

    stored_ = (char*) realloc (stored_, sizeof(char) * (strlen(testMessage) * (a+1) ));

    strcpy(&stored_[a], testMessage);
} 

for (int b = 0;b < 10; b++)
{
    printf("inside:|%s|\n",stored_[b]);
}

Ответы [ 2 ]

5 голосов
/ 21 декабря 2011

Fist up, sizeof(char) - это всегда 1, вам не нужно умножаться на него.

Во-вторых, когда вы выделяете место для строки, вы должныиспользуйте:

malloc (strlen (string) + 1);

Другими словами, вам нужно место для нулевого байта в конце.

В-третьих, вы, кажется, запутались между указателями на символы и указателем на символ указатель указатели.stored_ - это один блок символов, а stored_[1] - это только один байт после stored_[0], что означает, что у вас не будет достаточно места для хранения строки.

stored_[n], n=:   0   1   2   3
                +---+---+---+---+
                |   |   |   |   |...
                +---+---+---+---+
                each of these cells is a single byte.

Вам также придетсясамостоятельно управляйте одним блоком символов, оставляя достаточно места для каждого элемента (используя разреженные индексы), или используйте блок указателей символов с индексами 0, 1, 2 и т. д., но тогда вам придется управлять распределением строкотдельно.

Следующий код показывает, как это сделать:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main (void) {
    // An array of char pointers (C strings).

    char **stored_ = NULL;
    char testMessage[15];
    int i;

    // Populate them.

    for (i = 0; i < 10; i++) {
        sprintf (testMessage,"Message::%i",i);
        printf ("string is:%s;length is %i\n",testMessage,strlen(testMessage));

        // Reallocate array of char *, allocate room for string, then store it.

        stored_ =  realloc (stored_,sizeof (char*) * (i + 1));
        stored_[i] = malloc (strlen (testMessage) + 1);
        strcpy (stored_[i], testMessage);
    }

Суть этого в том, что выделение массива указателей символов отделяет отфактические массивы символов, образующие строки C.

Затем приведенный ниже код печатает их и очищает.

    // Print them.

    for (i = 0; i < 10; i++) {
        printf("inside:|%s|\n",stored_[i]);
    }

    // Free all memory and return.

    for (i = 0; i < 10; i++) {
        free (stored_[i]);
    }
    free (stored_);

    return 0;
}

Выходные данные, как и ожидалось:

string is:Message::0;length is 10
string is:Message::1;length is 10
string is:Message::2;length is 10
string is:Message::3;length is 10
string is:Message::4;length is 10
string is:Message::5;length is 10
string is:Message::6;length is 10
string is:Message::7;length is 10
string is:Message::8;length is 10
string is:Message::9;length is 10
inside:|Message::0|
inside:|Message::1|
inside:|Message::2|
inside:|Message::3|
inside:|Message::4|
inside:|Message::5|
inside:|Message::6|
inside:|Message::7|
inside:|Message::8|
inside:|Message::9|

При использовании этого метода каждая ячейка является указателем на массив символов, выделенный отдельно (который содержит строку C):

stored_[n], n=:   0   1   2   3
                +---+---+---+---+
                |   |   |   |   |...
                +---+---+---+---+
                  |   |   |   |     +----------------------+
                  |   |   |   +---> | character array here |
                  |   |   |         +----------------------+
                  |   |   |         +----------------------+
                  |   |   +-------> | character array here |
                  |   |             +----------------------+
                  |   |             +----------------------+
                  |   +-----------> | character array here |
                  |                 +----------------------+
                  |                 +----------------------+
                  +---------------> | character array here |
                                    +----------------------+
0 голосов
/ 21 декабря 2011

Вы, похоже, неправильно рассчитываете длину строки stored_.

Каждый цикл, который вы назначаете testMessage для &stored_[loopindex].Я не уверен, что это предполагаемое поведение, но это то, что вы делаете, поэтому я ожидаю, что ваша 10-я итерация выдаст строку "MMMMMMMMMessage::9\n".

В любом случае, testMessage всегда одинаковоколичество символов, поэтому пространство, необходимое для stored_, можно рассчитать следующим образом:

strlen(testMessage) // length of str to place at &stored_[a]
+ a                 // the loop index, where you're inserting testMessage
+ 1                 // important! extra char to hold the null terminator

Никогда не забывайте +1, каждая строка в C должна иметь место для нулевого терминатора .

...