memset 不使用指向字符的指针

Posted

技术标签:

【中文标题】memset 不使用指向字符的指针【英文标题】:memset is not working with pointer to character 【发布时间】:2016-10-11 01:57:23 【问题描述】:

以下代码有什么问题? 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;

【问题讨论】:

请勿在此处张贴文字图片。发布文本。 【参考方案1】:

您已经绊倒了 C++ 中一个非常古老的向后兼容缺陷,它继承自 C 并且可以追溯到 没有像 const 这样的东西的日子。字符串文字的类型为 const char [n],但是,除非您告诉编译器您不需要与 1990 年之前的代码兼容,否则它将默默地允许您设置 char * 变量以指向它们。但它不会允许您通过这样的指针进行写入。实际内存(尽可能)标记为只读;您观察到的“分段错误”错误是操作系统如何报告写入只读内存的尝试。

就语言规范而言,通过非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";
                   ^~~~~~~~~~~~~

在您获得足够的技能以了解何时不同的设置更合适之前,请使用-std=gnu++11 -Wall -Werror 或任何与您的编译器等效的东西来编译所有您的 C++ 程序。 (您似乎使用的是 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 *namechar name[];我也改变了其他一些东西,但只是为了展示更好的风格。这样做是强制编译器在进入main 时将字符串文字复制到可写 内存。 为什么在这里解释需要很长时间;参考一本好的 C++ 教科书。

【讨论】:

【参考方案2】:

自 2011 年以来,这不是有效的 C++ 代码,并且以前有过 UB。它是 C 中的 UB。

C++≥11:您不能将字符串文字分配给非const char 指针。

C++≥98 和 C:不能覆盖字符串文字。

把你的代码改成

char name[] = "SAMPLE TEXT";

您将拥有一个可以被覆盖的本地数组。

【讨论】:

【参考方案3】:

代码尝试修改字符串文字 ("SAMPLE TEXT") 的内容。这是不允许的。

【讨论】:

以上是关于memset 不使用指向字符的指针的主要内容,如果未能解决你的问题,请参考以下文章

在指向数组的指针上调用 memset?

memset清空指针是怎么用的?

C结构体成员初始化memset

memset 指针 + 偏移量

memset用法总结

使用memset()要注意