что имеет значение с этими двумя программами в C - PullRequest
0 голосов
/ 10 октября 2011

У меня есть две очень похожие программы, как показано ниже.

Программа A: нет проблем при запуске,

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

typedef struct p_struct{
   unsigned char* pulist;
   int length;
} list_type;

int get_struct(list_type* l)
{
   memset(l->pulist, 0, 4); 
   l->length=4;
}

int main ()
{
   list_type str;
   get_struct(&str);
}

Программа B: имеет дополнительный вызов функции, все еще компилируется, но завершается с ошибкой во время выполнения "Ошибка сегментации" с gcc.

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

typedef struct p_struct{
   unsigned char* pulist;
   int length;
} list_type;

int get_struct(list_type* l)
{
   memset(l->pulist, 0, 4); 
   l->length = 4;
}

int get_struct_a()
{
   list_type str;
   get_struct(&str);
}

int main ()
{
   get_struct_a();
}

Я действительно изо всех сил пытаюсь выяснить проблему здесь.Может кто-нибудь сказать мне, что вызывает "Ошибка сегментации"?Кроме того, почему программа B выдает ошибку «Ошибка сегментации», а программа A - нет?

Ответы [ 6 ]

5 голосов
/ 10 октября 2011

Вы не выделяете память для pulist члена вашей структуры. Следовательно, когда вы memset это, вы перезаписываете какую-то другую память в другом месте. Просто удача, что во втором случае память, которую вы перезаписываете, не дает segfault, но вы все еще портите память.

3 голосов
/ 10 октября 2011
memset(l->pulist, 0, 14);

Возможно, это его сбой.Вы не выделяете память для l->pulist, прежде чем пытаться использовать ее в качестве указателя на какую-то память.

Это

memset(l->pulist, 0, 4); 

Также должно произойти сбой, но он работает случайно.

Что происходит, вы выделяете один из этих struct s в стеке, и у всех членов есть какое-то случайное значение мусора (значение, которое оказалось в памяти, которую он выделил).Затем вы пытаетесь использовать одно из этих случайных значений в качестве указателя и говорите memset: «иди переписать 14 байтов в этом случайном месте с нулями».Вы можете понять, почему это может вызвать проблемы.Но так как указатель является случайным, он не всегда вызывает проблемы.

Вам нужно будет сделать что-то вроде

l->pulist = malloc(size);

Чтобы сделать его действительным указателемперед использованием в таких операциях.

3 голосов
/ 10 октября 2011

Вы никогда не инициализируете pulist для чего-либо, поэтому оно указывает куда угодно.Это просто чистое совпадение, что он падает в одном случае, но не в другом.

1 голос
/ 10 октября 2011

Ошибка сегментации возникает, когда программа пытается получить доступ к области памяти, к которой у нее нет доступа, или пытается получить доступ к области памяти способом, который не разрешен (например, при попытке записи только для чтения).или перезаписать часть операционной системы).

Несколько причин ошибки сегментации можно суммировать следующим образом:

  • при попытке выполнить программу, которая выполняетнеправильно скомпилировать.Обратите внимание, что большинство компиляторов не будут выводить двоичный файл при ошибке времени компиляции.

  • переполнение буфера.
  • с использованием неинициализированных указателей.
  • разыменование указателей NULL.
  • пытается получить доступ к памяти, которой не владеет программа.
  • пытается изменить память, которой не принадлежит программа (нарушение хранилища).
  • превышение допустимого размера стека (возможно, из-заубегающая рекурсия или бесконечный цикл)

Обычно ошибки сегментации возникают из-за того, что указатель имеет значение NULL, указывает на случайную память (вероятно, никогда не инициализируется) или указывает на память, которая была освобождена /перераспределена / "удален".

0 голосов
/ 10 октября 2011

Вы не инициализировали свой pulist член, чтобы указывать где-либо значимое;это просто содержит случайную битовую строку.В программе A эта случайная битовая строка соответствует адресу в памяти, который может быть записан.В программе B это не так.

Обе программы одинаково ошибочны.Когда вы создаете свой объект list_type, вам нужно явно установить элемент pulist, чтобы он указывал на ваш буфер.

0 голосов
/ 10 октября 2011

Я бы сказал, что элемент struct Pulist является неинициализированным указателем.Прежде чем использовать memset, вам нужно выделить немного памяти для этого члена.

...