Вопрос

Второй звонок к strcat Здесь генерирует ошибку сегментации, почему?

#include <unistd.h>
#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>  
#include <pthread.h>

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

         //if(scanf("%199s", command) == 1)

            gets(command);
            puts(command);

         int pipeIntId; 

         char whitespaceseparator[2]=" ";

         char pidstring [30];

         int pid= getpid(); 

         sprintf(pidstring,"%d", pid);

         char * whitespace_and_pid;

         whitespace_and_pid = strcat(whitespaceseparator,pidstring);  


         char * command_and_pid; 

         command_and_pid=strcat(command,whitespace_and_pid); // here's the problem, I guess


          if((mkfifo("pipe"/*pipeName*/,0666))==-1) 
          {
              perror("error creating pipe 1");
          exit(1);
          }

         if((pipeIntId=open("pipe",/*pipeName*/O_WRONLY))==-1)
         {
          perror("error creating pipe 2");
          exit(1);
         }


         int written;

         written=write(pipeIntId,command_and_pid,250); // send the command + the pid


         close(pipeIntId);

    return 0;
}
Это было полезно?

Решение

Я попробовал ваш код, а также увидеть SegFault на втором strcat(). Отказ я нашел это command[250] выделяется сразу после whitespaceseparator[2] На стеке в моей системе:

(gdb) p &whitespaceseparator 
$1 = (char (*)[2]) 0xbf90acd4
(gdb) p &command
$2 = (char (*)[250]) 0xbf90acd6

например (здесь command начинается "foo..."), все вкладываются так:

 whitespaceseparator
  |
  |      command
  |       |
  v       v
+---+---+---+---+---+---+---+---+
|' '| 0 |'f'|'o'|'o'|'.'|'.'|'.'| ...
+---+---+---+---+---+---+---+---+

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

Как другие сказали, strcat() Добавляет вторую строку в первый (и результат будет равен первым аргументом). Итак, первый strcat() переполнение whitespaceseparator[] (и возвращает whitespaceseparator в виде whitespace_and_pid):

+---+---+---+---+---+---+---+---+
|' '|'1'|'2'|'3'|'4'| 0 |'.'|'.'| ...
+---+---+---+---+---+---+---+---+

Второй strcat() пытается добавить whitespace_and_pid (== whitespaceseparator) в строку в command. Отказ Первый символ копии перезаписает завершение 0 строки в command:

  |    ===copy===>    |
  v                   v
+---+---+---+---+---+---+---+---+
|' '|'1'|'2'|'3'|'4'|' '|'.'|'.'| ...
+---+---+---+---+---+---+---+---+

Копия продолжается ...

      |    ===copy===>    |
      v                   v
+---+---+---+---+---+---+---+---+
|' '|'1'|'2'|'3'|'4'|' '|'1'|'.'| ...
+---+---+---+---+---+---+---+---+

          |    ===copy===>    |
          v                   v
+---+---+---+---+---+---+---+---+
|' '|'1'|'2'|'3'|'4'|' '|'1'|'2'| ...
+---+---+---+---+---+---+---+---+

и будет продолжать копирование " 1234 1234 1234"... пока он не падает с конца процесса адресного пространства, в какой момент вы получаете SegFault.

Другие советы

strcat не делает то, что вы думаете. Это модифицирует строку, указанную на свой первый параметр. В этом случае эта строка содержится в 2-байтовом массиве, который, следовательно, переполнен.

Чтобы избежать ошибок переполнения буфера, но используйте strcat Вы должны использовать strncat функция.

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

whitespaceseparator Не достаточно большие, чтобы содержать объединенную строку, поэтому вы вызываете неопределенное поведение.

С использованием gets обычно нахмурился тоже.

strcat Как правило, небезопасно, потому что он может с радостью перенапряжения буферов, как и в вашем случае.

Прежде всего, whitespaceseparator только два байта большими? Вы уверены, что вы хотите? И вы объединяете pidstring к этому? Я думаю, что вы получили аргументы, перепутанные.

В общем, хотя, strcat Приведет к сбою трудно отладки, если вы не очень осторожны с размерами буферов. Есть более безопасные альтернативы.

«Строкование Concatenation» - это идиома, которую вы должны упасть при изучении C. не только приводит к большому количеству ошибок с переполненными буферами; Это также сверхэффективно. В вашем коде вы могли бы просто включить место в snprintf Формат строки (вы должны использовать его вместо sprintf).

По возможности, попробуйте собрать строку полностью за один шаг, используя snprintf. Отказ Это объединяет всю проверку длины буфера в одно место и делает его действительно трудно ошибиться. Вы также можете позвонить snprintf Благодаря аргументу размера 0, чтобы получить длину, которую будет объединенная строка, чтобы узнать, какой размер для выделения, если размер выхода не известен заранее (вы должны выделить еще один байт, чем эта длина, чтобы Нулевой терминатор не обрезает ваш выход).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top