У меня проблемы с вставкой строки в массив в C - PullRequest
1 голос
/ 01 ноября 2010

У меня возникают проблемы с обнаружением того, что я делаю неправильно, вставляя строки в массив на C. Ниже приведен код. Строки printf показывают, что я действительно читаю правильные данные - но после того, как я вставляю каждую строку данных в массив - я затем проверяю ее, чтобы найти, что каждый элемент массива заполнен последней строкой, помещенной в массив .

// Фрагмент кода

char outbuf[BUFFER_LEN];
int std_out_count = 0;
char *std_out_lines[BUFFER_LEN]; /* Array to hold STDOUT */

while ((i = read(stdout_pipe_fds[0], outbuf, BUFFER_LEN - 1)) > 0) {
  outbuf[i] = '\0';
  char temp[BUFFER_LEN];
  printf("PARENT read from stdout: %s\n", outbuf);
  strcpy(temp, outbuf);
  std_out_lines[std_out_count] = temp;
  std_out_count++;
}

printf("STDOUT_COUNT: %i\n", std_out_count); /* Print out elements of array to make sure they're correct */
int idx;
for(idx = 0; idx < std_out_count; idx++) {
  printf("STDOUT[%i]: %s\n", idx, std_out_lines[idx]);
}

// По этим выводам я вижу, что я читаю правильные значения

/ * PARENT читает из stdout: STDOUT =: это номер строки 0:

PARENT читается из stdout: STDOUT =: это строка номер 1:

PARENT читается из stdout: STDOUT =: это строка № 2: * /

// Но когда я проверяю элементы массива - каждый элемент заполняется последней прочитанной строкой; (

/ * STDOUT_COUNT: 3 STDOUT [0]: STDOUT =: это строка № 2:

STDOUT [1]: STDOUT =: это строка № 2:

STDOUT [2]: STDOUT =: это строка № 2: * /

Ответы [ 3 ]

3 голосов
/ 01 ноября 2010

Эта строка:

char *std_out_lines[BUFFER_LEN];

выделяет массив символов указателей , но не выделяет места для самих фактических данных.

Позже, когда выdo:

char temp[BUFFER_LEN];
printf("PARENT read from stdout: %s\n", outbuf);
strcpy(temp, outbuf);
std_out_lines[std_out_count] = temp;

вы на самом деле перезаписываете такой же фрагмент памяти, который каждая новая строка и сохраняет (неизменяемый) адрес в следующем символьном указателе. char temp[BUFFER_LEN]; не делаетвыдает новую область данных каждый раз, когда она выполняется.

Вот почему она работает.Однако, когда temp выходит из области видимости, я бы не советовал пытаться исследовать какие-либо строки, на которые указывает ваш массив.Это неопределенное поведение.Кажется, это работает для вас, но я гарантирую, что это чисто случайно: -)

Вы можете захотеть посмотреть на дублирование строки, чтобы каждый элемент массива имел свою собственную копию.Замените:

std_out_lines[std_out_count] = temp;

на:

std_out_lines[std_out_count] = strdup(temp);

или просто канаву temp в целом и используйте:

std_out_lines[std_out_count] = strdup(outbuf);

Это дает копию строки и дает вам адрес для хранения в массиве, так что они все отделены друг от друга.Просто помните, что вы, вероятно, должны в конце концов освободить эту память.


При маловероятной вероятности того, что ваша реализация C не имеет a strdup (это не предписано ISOстандарт), вот тот, который я подготовил ранее .

1 голос
/ 01 ноября 2010

Вы вставляете указатель на выделенный стеком буфер 'temp', который большую часть времени будет совпадать с указателем.

Измените код цикла while на:

  outbuf[i] = '\0';
  printf("PARENT read from stdout: %s\n", outbuf);
  std_out_lines[std_out_count] = strdup(outbuf);
  std_out_count++;

strdup () выделит память для строки, вставленной в массив std_out_lines, и скопирует содержимое outbuf в эту новую строку.

1 голос
/ 01 ноября 2010

Вам нужно выделить некоторое хранилище, а не использовать временную переменную temp.

В настоящее время вы повторно используете переменную temp каждый раз вокруг цикла.

Используйте что-то вроде

std_out_lines[i] = malloc(BUFFER_LEN);
// check for null here too, malloc can fail.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...