2015-06-01 5 views
0

До сих пор у меня был код, который отлично работал с переменной wfiles. wfiles инициализируется в моем основном файле:Ошибка сегментации при вызове strlen с ранее выделенным указателем

char* wfiles = ""; 

Какой, насколько я могу судить, C не имеет жалоб. Далее переменная wfiles выделяется в распределительном заявление:

switch (c) { 
    case 't': 
     /* the user wants a template */ 
     template = optarg; 
     break; 
    case 'f': 
     wfiles = optarg; 
     break; 
    case 'v': 
     vcs = optarg; 
     break; 
    case 'u': 
     url = optarg; 
     break; 
    case 's': 
     /* custom save location */ 
     save_loc = optarg; 
     break; 
    case '?': 
     break; 
    default: 
     abort(); 
    } 

я, наконец, проверить на ли или нет wfiles пуст:

if (!empty(wfiles)) 

пустой макрос, который расширяется до (strlen(wfiles) == 0)

я не могу см. любые проблемы с этим, но когда я запускаю этот код, я получаю ошибку сегментации. Раньше этого не было. Когда я запускал код в gdb с и без отладочных символов, я получаю одну строку, указывающую на ранее упомянутое утверждение if. Кто-нибудь знает, почему это?

+1

Проблема в другом месте. Код, который вы показали, кажется, не имеет проблем. –

+0

Откуда вы получаете 'optarg'? Поскольку единственным назначением 'wfiles' является' optarg', очень вероятно, что память, на которую он указывала, когда она была назначена, больше недействительна, когда вы вызываете 'strlen' позже –

+0

@intricatedetail Просто выводите строку и ее адрес и все будет ясно. :) –

ответ

2

strlen() будет разыменовывать указатель, что может вызвать некоторые проблемы, когда этот указатель, т. Е. optarg, недействителен.

Например, в случае optarg=NULL и c='f', ваш код будет выполняться как:

case 'f': 
    wfiles = optarg; 
    //Now wfiles=NULL 

strlen(wfiles) будет: происходит ошибка strlen(NULL) и сегментации.

См this related question для получения дополнительной справки

+0

Спасибо, что я никогда не знал об этом, я настраивал свой макрос, и он работал нормально. – intricatedetail

3

EDIT:

Как уже упоминалось в других ответах, действительно вам нужно проверить на NULL, прежде чем передать указатель на strlen(). В вашем случае optarg может очень содержать NULL. Итак, лучше поместите NULL-проверку против входящего указателя в empty() MACRO.

Однако нижеследующая точка все еще действительна, поэтому сохраняйте ее как есть.


Я думаю, ваша проблема может быть с тем, как вы назначитьoptargwfiles к. optarg может меняться при разных итерациях. Таким образом, только , указывая на optarg, может дать вам безупречный результат. Вам необходимо указать копию содержание optarg для этой конкретной итерации.

Вместо назначения (хранения) указатель, попробуйте

  • выделения памяти для wfiles.
  • strcpy()optarg до wfiles.

Или вы можете использовать strdup() напрямую.

2

Вы можете защитить макрос empty от 1 й тестирования является ли ее аргумент указывает на NULL перед вызовом strlen().

#define empty(s) (s) ?(0 == strlen(s)) :1 
+1

Или более безопасный, быстрый и читаемый: 'inline bool is_empty (const char * str) {if (str == NULL) {return true; } return * str == '\ 0'; } '. Но, конечно, если остальная часть программы была без ошибок, указатель никогда не был бы NULL в любом случае. – Lundin