Необработанное исключение при разыменовании указателя на символ в Visual C ++ 2008 - PullRequest
2 голосов
/ 11 июля 2009

Я пытаюсь сделать некоторую классическую разработку на C в Visual C ++ 2008, которая будет изменять символы строки следующим образом:

void ModifyString(char *input)
{
  // Change first character to 'a'
  *input = 'a';
}

Я получаю необработанное исключение, когда пытаюсь сменить персонажа. Кажется, что я мог бы сделать это в Visual Studio 6 или с помощью gcc, но, возможно, я просто что-то забыл. Visual Studio каким-то образом передает char * по значению (управление памятью). Если да, то как мне это отключить?

Ответы [ 4 ]

8 голосов
/ 11 июля 2009

Вы, вероятно, передаете строковый литерал где-то:

ModifyString("oops");  // ERROR!

C и C ++ позволяют вам неявно приводить из строковых литералов (которые имеют тип const char[]) к char*, но такое использование не рекомендуется. Строковые константы могут быть размещены в постоянной памяти (и они обычно есть), поэтому, если вы попытаетесь изменить их, вы получите нарушение прав доступа (иначе ошибка сегментации или ошибка шины). Если компилятор не помещает строковые константы в постоянную память, программа все равно будет работать, но это неопределенное поведение.

Правильный способ сделать это - скопировать строку в буфер для записи:

// one way:
char mystring[] = "test";
ModifyString(mystring);  // ok

// another way:
char mystring[64];  // make sure this is big enough!!
strcpy(mystring, "test");
ModifyString(mystring);  // ok
1 голос
/ 11 июля 2009

Невозможно ответить на этот вопрос, не видя, как вызывается ModifyString. Сама функция верна, если ее контракту передано ненулевое значение.

Однако сайт вызова может потерпеть неудачу, выполнив любое количество действий

  • Передача NULL
  • Передача константного чар с помощью злого заклинания
1 голос
/ 11 июля 2009

Является ли ввод строковым литералом? Это, наверное, проблема. В противном случае вам нужно будет разместить больше кода, так как указатель каким-то образом оказался в памяти только для чтения.

0 голосов
/ 11 июля 2009

Я не могу точно сказать, почему это не работает, но проблема в вашем коде, а не в Visual Studio. По какой-то причине вы передаете недопустимый указатель на функцию. Это либо нулевой указатель, либо он указывает на какой-то адрес, к которому у вас нет прав на чтение.

Если вы разместите еще немного кода (откуда вызывается функция и как она называется?), Мы можем указать на точную проблему.

Причина, по которой он работал в GCC или VC6, заключается в том, что это неопределенное поведение. Стандарт C ++ не говорит, что «это должно работать» или «это должно вызвать сбой». Все может произойти, если вы пишете в память, к которой у вас нет доступа. И в зависимости от компилятора и системы, на которой вы запускаете приложение, адрес, к которому вы обращаетесь, будет различаться. По счастливой случайности вы попали по адресу, который вызвал нарушение прав доступа при компиляции с VC2008. Под GCC и VC6 вам не повезло, и вы получили код, который , казалось, работал , и просто написал на какой-то мусорный адрес.

...