Как может, разыменовывая Нулевого указателя в C не, разрушают программу?

Как насчет того, чтобы установить его с JavaScript?

var e = document.getElementById('cardNumber');
e.autocomplete = 'off'; // Maybe should be false

Это не прекрасно, но Ваш HTML будет допустим.

13
задан Mecki 27 August 2009 в 17:33
поделиться

16 ответов

It is possible that the structure is located in memory that has been free()'d, or the heap is corrupted. In that case, malloc() could be modifying the memory, thinking that it is free.

You might try running your program under a memory checker. One memory checker that supports Mac OS X is valgrind, although it supports Mac OS X only on Intel, not on PowerPC.

11
ответ дан 1 December 2019 в 19:02
поделиться

* результат = malloc (realLength); // ???

Адрес вновь выделенного сегмента памяти сохраняется в месте, на которое ссылается адрес, содержащийся в переменной «результат».

Это намерение? Если это так, возможно, потребуется изменить strlcpy.

0
ответ дан 1 December 2019 в 19:02
поделиться
char * p = NULL;

p[i] is like

p += i;

which is a valid operation, even on a nullpointer. it then points at memory location 0x0000[...]i

0
ответ дан 1 December 2019 в 19:02
поделиться

Вы всегда должны проверять, является ли информация-> kind.name-> data нулевым значением, но в этом случае

в

if (*result == NULL) 
    freeParsedData(information);
    return -1;
}

вы пропустили {

, это должно быть

if (*result == NULL)
{ 
     freeParsedData(information);
     return -1;
}

Это веская причина для использования этого стиля кодирования вместо

if (*result == NULL) { 
    freeParsedData(information);
    return -1;
}

, где вы можете не заметить недостающую скобку, потому что вы привыкли к форме блока кода без скобки, отделяющей его от предложения if.

0
ответ дан 1 December 2019 в 19:02
поделиться

Вау, это странно. Одна вещь кажется мне немного подозрительной, хотя она может и не способствовать:

Что произошло бы, если бы информация и данные были хорошими указателями (не нулевыми), а значение information.kind.name было нулевым. Вы не разыменовываете этот указатель до строки strlcpy, поэтому, если он был нулевым, он мог не аварийно завершить работу до этого момента. Конечно, раньше, чем вы выполняете разыменование данных [1], чтобы установить их в \ 0, что также должно привести к сбою, но из-за какой-либо случайности ваша программа может просто иметь доступ на запись к 0x01, но не к 0x00.

Кроме того, я вижу, что вы используете информацию-> name.length в одном месте, а информацию-> kind.name.length в другом, не уверен, что это опечатка или желательно.

0
ответ дан 1 December 2019 в 19:02
поделиться

Отсутствие символа '{' после последнего оператора if означает, что что-то в разделе «// ... код выше пропущен, не имеет отношения ...» контролирует доступ ко всему этому фрагменту кода. Из всего вставленного кода выполняется только strlcpy. Решение: никогда не используйте операторы if без фигурных скобок для пояснения элемента управления.

Учтите это ...

if(false)
{
    if(something == stuff)
    {
        doStuff();

    .. snip ..

    if(monkey == blah)
        some->garbage= nothing;
        return -1;
    }
}
crash();

Только "crash ();" будет казнен.

1
ответ дан 1 December 2019 в 19:02
поделиться

Несмотря на то, что разыменование нулевого указателя приводит к неопределенному поведению и не обязательно к сбою, вы должны проверить значение информация-> вид.имя-> данные а не содержимое информация-> вид.имя-> данные [1] .

0
ответ дан 1 December 2019 в 19:02
поделиться

Я бы запустил вашу программу под valgrind . Вы уже знаете, что существует проблема с указателями NULL, поэтому профилируйте этот код.

Преимущество того, что здесь существует valgrind, состоит в том, что он проверяет каждую ссылку на указатель и проверяет, была ли эта ячейка памяти ранее объявлена, и сообщит вам номер строки, структура и все, что вам нужно знать о памяти.

Как уже упоминалось, ссылка на ячейку памяти 0 - это своего рода «que sera, sera».

Мое паучье чутье с оттенком C - это говоря мне, что вы должны разбить эти структурные переходы на линии

if (information->kind.name->data[information->kind.name->length] != '\0') {

, например,

    if (information == NULL) {
      return -1; 
    }
    if (information->kind == NULL) {
      return -1; 
    }

и так далее.

1
ответ дан 1 December 2019 в 19:02
поделиться

Меня интересует приведение символов * в вызове strlcpy.

Могут ли данные типа * отличаться по размеру от символа * в вашей системе? Если указатели символов меньше, вы можете получить подмножество указателя данных, которое может иметь значение NULL.

Пример:

int a = 0xffff0000;
short b = (short) a; //b could be 0 if lower bits are used

Изменить : орфографические ошибки исправлены.

1
ответ дан 1 December 2019 в 19:02
поделиться

Моя теория состоит в том, что информация-> вид.имя-> длина является очень большим значением, так что информация-> вид.имя-> данные [информация -> kind.name-> length] на самом деле относится к действительному адресу памяти.

2
ответ дан 1 December 2019 в 19:02
поделиться

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

1
ответ дан 1 December 2019 в 19:02
поделиться

As an FYI, when I see this line:

if (information->kind.name->data[information->kind.name->length] != '\0') {

I see up to three different pointer dereferences:

  1. information
  2. name
  3. data (if it's a pointer and not a fixed array)

You check information for non-null, but not name and not data. What makes you so sure that they're correct?

I also echo other sentiments here about something else possibly damaging your heap earlier. If you're running on windows, consider using gflags to do things like page allocation, which can be used to detect if you or someone else is writing past the end of a buffer and stepping on your heap.

Saw that you're on a Mac - ignore the gflags comment - it might help someone else who reads this. If you're running on something earlier than OS X, there are a number of handy Macsbugs tools to stress the heap (like the heap scramble command, 'hs').

1
ответ дан 1 December 2019 в 19:02
поделиться

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

3
ответ дан 1 December 2019 в 19:02
поделиться

Эффект разыменования нулевого указателя не определен стандартом, насколько мне известно.

Согласно стандарту C 6.5.3.2/4:

Если указателю присвоено недопустимое значение, поведение унарного оператора * не определено.

Так что сбой может быть, а может и не быть.

5
ответ дан 1 December 2019 в 19:02
поделиться

Here's one specific way you can get past the 'data' pointer being NULL in

if (information->kind.name->data[information->kind.name->length] != '\0') {

Say information->kind.name->length is large. Atleast larger than 4096, on a particular platform with a particular compiler (Say, most *nixes with a stock gcc compiler) the code will result in a memory read of "address of kind.name->data + information->kind.name->length].

At a lower level, that read is "read memory at address (0 + 8653)" (or whatever the length was). It's common on *nixes to mark the first page in the address space as "not accessible", meaning dereferencing a NULL pointer that reads memory address 0 to 4096 will result in a hardware trap being propagated to the application and crash it.

Reading past that first page, you might happen to poke into valid mapped memory, e.g. a shared library or something else that happened to be mapped there - and the memory access will not fail. And that's ok. Dereferencing a NULL pointer is undefined behavior, nothing requires it to fail.

1
ответ дан 1 December 2019 в 19:02
поделиться

Во-первых, разыменование нулевого указателя является неопределенным поведением. Это может привести к сбою, но не к сбою или установке обоев на изображение Губки Боба Квадратные Штаны.

Тем не менее, разыменование нулевого указателя обычно приводит к сбою. Таким образом, ваша проблема, вероятно, связана с повреждением памяти, например, из-за записи после конца одной из ваших строк. Это может вызвать сбой с отсроченным эффектом. Я особенно подозреваю, потому что маловероятно, что malloc (1) выйдет из строя, если только ваша программа не столкнется с концом доступной виртуальной памяти, и вы, вероятно, заметили бы, если бы это было так.

Edit: OP указал, что нулевым результатом является не результат, а информация-> вид.имя-> данные . Вот потенциальная проблема:

Нет проверки для информации-> kind.name-> data имеет значение null. Единственная проверка на это -

if (information->kind.name->data[information->kind.name->length] != '\0') {

. Предположим, что information-> kind.name-> data имеет значение null, но information-> kind.name-> length, скажем, равно 100. Тогда это утверждение будет эквивалент:

if (*(information->kind.name->data + 100) != '\0') {

Что не разыменовывает NULL, а разыменовывает адрес 100. Если это не приводит к сбою и адрес 100 содержит 0, то этот тест будет пройден.

13
ответ дан 1 December 2019 в 19:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: