字符数组指针拷贝地址异常及绕过类成员const限定符的问询
关于绕过const限定性的内存地址异常问题
C++代码示例
StringView.hh
#pragma once #include <cstring> class StringView { public: const char* _begin = nullptr; const char* _end = nullptr; explicit StringView(const char* str) : _begin(str), _end(str + strlen(str)) {} };
main.cpp
#include <iostream> #include "StringView.hh" int main() { char str[] = "cat"; StringView sv(str); std::cout << str << '\n'; void *pointer = reinterpret_cast<void *>(&sv); // *(char *) pointer = 'b'; // 我还想把它设置成整个字符串,但这样不行,如果是std::string就可以,但char*不行,或许char**可以? // std::cout << str << '\n'; std::cout << "Pointer to StringView: " << pointer << "\n"; std::cout << "String: " << (void *)str << "\n"; std::cout << "String from StringView _begin: " << (void *)sv._begin << "\n"; return 0; }
未注释代码时的运行结果
cat Pointer to StringView: 0xe25bffde0 String: 0xe25bffdf4 String from StringView _begin: 0xe25bffdf4
此时str和StringView::_begin指向同一地址,但取消注释*(char *) pointer = 'b';后,运行结果变为:
cat cat Pointer to StringView: 0x81491ffc50 String: 0x81491ffc64 String from StringView _begin: 0x81491ffc62
三者地址均发生变化,请问该现象的原因是什么?是否存在不使用const_cast即可绕过const限定的方法?
C语言代码示例
#include <stdio.h> #include <string.h> struct StringView { const char* _begin; const char* _end; }; struct StringView create(const char *str) { struct StringView a = {str, str + strlen(str)}; return a; } int main() { char str[] = "cat"; struct StringView sv = create(str); printf("%s\n", str); void *pointer = (void *) &sv; *(char *) pointer = 'b'; printf("%s\n", str); printf("Pointer to StringView: %p\n", pointer); printf("String: %p\n", (void *)str); printf("String from StringView _begin: %p\n", (void *)sv._begin); return 0; }
注:我知道非对象内的const字符串存储在只读内存中,因此未将
str声明为const char[],但仍出现内存地址变化的情况;且未使用std::string,因其重载赋值运算符会破坏const限定性。
问题解答
1. 地址异常的原因
你执行的*(char *) pointer = 'b';是直接修改了StringView对象本身的内存字节,而非修改_begin指向的字符串内容:
- 64位系统中,
StringView的两个const char*成员各占8字节,对象总大小为16字节。 pointer指向sv的起始地址,*(char*)pointer = 'b'修改的是_begin指针的第一个字节。原本_begin存储的是str的地址,修改后指针值被破坏,变成了错误地址,因此sv._begin的输出地址和原str地址不一致。- 至于
StringView自身地址变化,是程序每次运行时栈内存布局的正常波动,和修改操作无直接关联,核心问题是_begin指针被篡改。
2. 不使用const_cast绕过const限定的方法
仅当const char*指向的是非const内存(比如你的_begin指向char[]类型的str)时,以下操作是合法的:
- C++方式:将指针转换为
char**,间接修改目标字符串:
或者直接转换指针后修改:char** begin_ptr = reinterpret_cast<char**>(&sv._begin); **begin_ptr = 'b'; // 修改str的第一个字符char* mutable_str = reinterpret_cast<char*>(sv._begin); mutable_str[0] = 'b'; - C语言方式:类似地转换指针类型修改:
char** begin_ptr = (char**)&sv._begin; **begin_ptr = 'b';
注意:如果const char*指向的是真正的const字符串(比如const char* str = "cat"),修改其指向的内存属于未定义行为,可能导致程序崩溃或异常。
内容的提问来源于stack exchange,提问作者ashamedgap
相关产品推荐
相关产品推荐

