2016-10-11 2 views
-1

Что не так в следующем коде? Предполагается, что memset работает с указателем на блок памяти для заполнения. Но этот код отображает проблемы в консоли говоря ошибки сегментации (ядро сбрасывали)memset не работает с указателем на символ

#include<iostream> 
#include <cstring> 
using namespace std; 

int main(int argc, char** argv) 
{ 
    char* name = "SAMPLE TEXT"; 
    memset(name , '*', 6); 
    cout << name << endl; 
    return 0; 
} 

screenshot of the above program catching a segmentation fault

+0

Не размещайте фотографии текста здесь. Отправьте текст. – EJP

ответ

3

Это не действительный C++ код с 2011 года, и был UB когда-либо прежде. Это UB в C.

C++ ≥11: Вы не можете назначать строковые литералы для не-constchar указателей.

C++ ≥98 и C: Вы не можете перезаписывать строковые литералы.

изменить код

char name[] = "SAMPLE TEXT"; 

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

0

Код пытается изменить содержимое строкового литерала ("SAMPLE TEXT"). Это не разрешено.

7

Вы споткнулись очень старая бородавка обратной совместимости в C++, унаследованный от C и датированный дни, когда было нет такого понятия, как const. Строковые литералы имеют тип const char [n], но, если вы не сообщите своему компилятору, что вам не нужно быть совместимым с кодом до 1990 года, он беззвучно позволит вам указать char * переменные, чтобы указать на них. Но это не будет позволяет писать через такой указатель. Фактическая память (по возможности) отмечена только для чтения; ошибка «segmentation fault», которую вы наблюдаете, - это то, как операционная система сообщает о попытке записать в постоянную память.

С точки зрения спецификации языка, запись const данных через не- const указатель - однако вам удалось установить, что - есть «неопределенное поведение», которое является причудливым способом сказать «программа неправильна, но компилятор не должен выдавать диагностику, и если вы получите скомпилированный исполняемый файл, он может сделать что-нибудь. " «Ошибка сегментации» почти всегда означает, что ваша программа имеет неопределенное поведение в ней где-то.

Если я скомпилировать программу с соответствующими настройками, я получаю сообщение об ошибке:

$ g++ -std=gnu++11 -Wall -Werror test.cc 
test.cc: In function ‘int main(int, char**)’: 
test.cc:7:19: error: ISO C++ forbids converting a string constant to ‘char*’ 
[-Werror=write-strings] 
     char* name = "SAMPLE TEXT"; 
        ^~~~~~~~~~~~~ 

Пока вы не получите достаточно навыков, чтобы знать, когда различные настройки являются более подходящими, компилировать все свои программы на C++ с -std=gnu++11 -Wall -Werror, или независимо от вашего эквивалента компилятора. (Вы, кажется, использует операционную систему Unix-ароматизатора, так что эти параметры должны работать. Вы также можете -g и/или -O.)

Ваша программа может быть сделано, чтобы работать, изменяя его читать

#include <iostream> 
#include <cstring> 

int 
main() 
{ 
    char name[] = "SAMPLE TEXT"; 
    std::memset(name, '*', 6); 
    std::cout << name << '\n'; 
    return 0; 
} 

=>

$ g++ -std=c++11 -Wall -Werror test.cc 
$ ./a.out 
****** TEXT 

изменение, которое фиксирует ошибку от char *name к char name[]; Я изменил и другие вещи, но только для того, чтобы продемонстрировать лучший стиль.То, что это делает, заставляет компилятор копировать строковый литерал в записываемый память при записи до main. Почему это делает слишком долго, чтобы объяснить здесь; проконсультируйтесь с хорошим учебником на C++.

Смежные вопросы