Segfault при доступе к char[]

у меня есть функция

int foo() {
    ...
    char* real_path_buffer = (char*)malloc(sizeof(char)*PATH_MAX);
    realpath("a/certain/path/that/doesnt/exist", real_path_buffer);
    ...
}

Это вызов realpath в Android bionic.

char* realpath(const __restrict char*, __restrict char*){
    char path1[PATH_MAX], path2[PATH_MAX], path3[PATH_MAX];
    ...
    path1 = something_valid; //recall, this is a library function
    ...
    memcpy(path2, path1, a_valid_size);
    ...
}

И при передаче определенного несуществующего пути к realpath из производственного сценария я получаю segfault при доступе к path2 любым способом (это происходит, когда я просто пытаюсь напечатать его, а также memcpy к нему).

Я проверил, что программе не не хватает памяти, когда происходит segfault (сделав вызов malloc и убедившись, что он возвращает не NULL), но вы можете быть уверены, что этот вызов происходит на довольно большом стеке.

Я также проверил, что в менее интенсивных путях кода realpath точно возвращает NULL без ошибок сегментации.

У кого-нибудь есть идеи, почему это происходит?


person Reuben Tanner    schedule 18.02.2015    source источник
comment
Каково значение PATH_MAX?   -  person user3386109    schedule 19.02.2015
comment
Большое количество определено в ‹linux/limits.h›   -  person Reuben Tanner    schedule 19.02.2015
comment
Да, дело в том, что вам нужно знать, что это за число, чтобы оценить, вызовут ли 3 массива такого размера в стеке переполнение стека. Конечно, вам также необходимо знать, насколько велик стек и насколько глубоко вы находитесь в стеке, когда вызываете realpath.   -  person user3386109    schedule 19.02.2015
comment
Да, это звучит правильно. Как я могу определить эти вещи (размер стека, с которым я работаю, и мою текущую глубину в стеке)?   -  person Reuben Tanner    schedule 19.02.2015
comment
Размер стека — это большое число, определенное в документации Android. Вы можете найти (приблизительную) текущую глубину, взяв адрес локальной переменной в функции верхнего уровня (сохраненной как глобальная переменная) и вычитая адрес локальной переменной в некоторой функции более низкого уровня. Обратите внимание, что оба адреса должны быть преобразованы в char *, чтобы получить глубину стека в байтах.   -  person user3386109    schedule 19.02.2015


Ответы (1)


Я не смог полностью проверить это, но я считаю, что это было переполнение стека.

person Reuben Tanner    schedule 06.03.2015
comment
Если исходная проблема повторяется, можно было бы подумать, что вы можете проверить это с помощью выделения стека аналогичного размера, а не с запуском того же кода с меньшей глубиной стека. - person Chris Stratton; 06.03.2015