ошибка сегментации во время выполнения

#c #ansi

#c #ansi-c

Вопрос:

 #include<stdio.h>   
int main()  
{    
    char *arg[10],*c;  
    int count=0;  
    FILE *fp,*fq;  
    printf("Name of the file:");  
    scanf("%s",arg[1]);  
    fp=fopen(arg[1],"w");  
    printf("tt%s",arg[1]);  
    printf("Input the text into the filen");  
    printf("Press Ctrl d to the stopn");  
    while((*c=getchar())!=EOF)  
    {  
            fwrite(c,sizeof(char),1,fp);  
            count  ;  
    }  
    return 0;  
}  
  

Комментарии:

1. домашнее задание? Нет проблем, если это так. Просто отметьте это, чтобы вы могли получить лучшие ответы

2. вы могли бы, по крайней мере, написать что-нибудь от себя

3. Вам действительно следует перейти к codereview.stackexchange.com если все, что вы делаете, это отправляете код

4. По крайней мере, напишите в своем сообщении что-нибудь, что позволит нам узнать, в чем заключается ваш вопрос, вместо того, чтобы заставлять нас предполагать, что вы хотите знать, почему происходит сбой seg.

5. Примечание: Научитесь использовать отладчик. По крайней мере, достаточно, чтобы выяснить, какая строка выдает ошибку (для gcc в Linux это было бы gdb program n run n [wait until it stops] bt n , другие системы будут отличаться, но все равно будут иметь эту функциональность). Тогда вы, возможно, поняли бы это сами и смогли бы показать нам более короткий и понятный пример кода.

Ответ №1:

Измените эту строку

 char *arg[10],*c;
  

Для

 char arg[1000],c;
  

Эта строка

 scanf("%s",arg[1]);  
  

Для

 scanf("%s",arg);  
  

И эта строка

 while((*c=getchar())!=EOF)
  

Для

 while((c=getchar())!=EOF)
  

Объяснение:

char *c; не является символом. Это указатель на символ. Это начинается с простого указания на случайный бит памяти, который часто будет заполнен случайными данными — независимо от того, что там было записано совсем недавно.

char c; является символом.

То же самое относится к char *arg[10] . Это массив из десяти указателей. Они указывают на случайную память, заполненную случайными данными.

Примечание: мое изменение не является лучшей практикой. Если бы кто-то ввел имя файла длиной 1000 символов или больше, вы бы написали поверх конца arg буфера. В зависимости от того, что вы делаете, это может быть ошибкой безопасности.

Комментарии:

1. я использовал char *, чтобы у 1 аргумента fwrite был указатель, и я не хотел искать файл. Я внес необходимые изменения, такие как *arg [] на arg [1000], char * c на char c, но я добираюсь до ошибки сегментации. Мое намерение состоит в том, чтобы изменить содержимое файла и вставить его в другой файл. Приведенная выше программа является частью этого.

Ответ №2:

В

 char *arg[10];
  

вы определяете массив из 10 указателей на char , но не инициализируете его элементы. аргументы [0], arg[1], …, arg[9] будут иметь неопределенные значения.

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

Комментарии:

1. Я не вижу здесь никакой ошибки. Почему понижающий голос? Голосование за баланс 🙂

2. Я не понизил голос, и я бы не стал понижать голос за это, но «ваша программа могла бы вместо этого отформатировать ваш жесткий диск» немного перегибает палку…

3. Несмотря на умную ссылку, компилятор может генерировать любой код, который ему нравится, нет современной ОС, которая позволит ему форматировать HD. Я придерживаюсь чрезмерной загрузки.

4. @Jon: Я постараюсь не забыть использовать мой другой пример UB в будущем … заставляет компьютер выделять лимонный сок из USB-порта

5. @pmg Я на самом деле предпочитаю это. Передает суть более кратко 🙂

Ответ №3:

 char *arg[10] ;
  

arg это массив указателей на символы. Вам необходимо назначить им ячейки памяти с помощью malloc перед приемом ввода —

 scanf("%s",arg[1]); // arg[1] is not assigned to point to any memory location
                    // and is what causing the segmentation fault.
  

Так что —

 arg[1] = malloc( stringLengthExpectedToEnter   1 ) ; //  1 for termination character
  

То же самое следует проделать и с остальными элементами массива (или) просто измените char*arg[10] на char arg[10] и убедитесь, что вводите только 9 символов.


Я думаю, вы путаете указатель и обычную переменную.

 int *ptr;
  

ptr является переменной, которая может содержать адрес целочисленной переменной. Для ptr переменной выделена память для хранения целочисленного адреса. Вот и все. ptr находится в неинициализированном состоянии и не указывает, где (или) может указывать на мусор. Поведение разыменования неинициализированного указателя не определено, и вам повезет, если это приведет к ошибке сегментации.

Теперь вам нужно назначить ему допустимую ячейку памяти с помощью malloc .

 ptr = malloc( sizeof(int) ) ; // Allocates number of bytes required to hold an
                              // integer and returns it's address.
  

Итак, ptr теперь указывает на ячейку памяти, полученную из бесплатного хранилища, которая может содержать целое число. Такие приобретенные местоположения из свободного хранилища должны быть освобождены с помощью free , иначе у вас классическая проблема утечки памяти. Хорошей практикой является инициализация указателя на NULL при объявлении.

 int *ptr = NULL ;
  

Надеюсь, это поможет!

 scanf("%d", ptr) ; // Notice that amp; is not required before ptr. Because ptr 
                   // content is address itself.
  

История с обычной переменной совершенно иная. При объявлении —

 int var ;
  

Для var хранения целого числа выделена память. Таким образом, вы можете напрямую присвоить ему целое число.

Комментарии:

1. Хорошее объяснение, но здесь у меня есть сомнения. Является ли память указателя статической или она сохраняется постоянно после выхода из программы (если я не выделил для нее память динамически) и где хранится память, как в аргументах командной строки ex- int main(argc ,*argv[])……

Ответ №4:

 #include<stdio.h>   
int main()  
{    
   char arg[10],c;  
   int count=0;  
   FILE *fp;  
   printf("Name of the file:");  
   scanf("%s",arg);  
   fp=fopen(arg,"w");  
   printf("tt%s",arg);  
   printf("Input the text into the filen");  
   printf("Press Ctrl d to the stopn");  
   while((c=getchar())!=EOF)  
   {  
        fwrite(amp;c,sizeof(char),1,fp);  
        count  ;  
   }

   if(fp != NULL){
      fclose(fp);
      fp = NULL;
   }
   return 0;  
}