C++11(VS2017)字符串XOR编码实现问题求助
让我逐个拆解你遇到的问题,然后给出靠谱的修复方案:
你的三个尝试分别错在哪里?
1. 强制转换字符串字面量为char*
字符串字面量(比如"Hello World!")在C++标准里是**const char*类型**,它们被存储在程序的只读数据段中。你强行把它转成char*去修改,本质是在尝试修改只读内存,这属于未定义行为,触发内存访问异常是必然的结果——操作系统会直接阻止这种非法操作。
2. 返回栈上的局部数组指针
你在encode函数里声明的temp[128]是栈内存上的局部变量,当函数执行完毕返回时,栈帧会被销毁,这块内存会被标记为可复用。此时返回的指针就变成了野指针,指向的内存已经不属于你的程序,后续访问它会导致栈损坏、程序崩溃等不可预测的问题。
另外这里还有个小坑:你用strncpy(temp, input, 128),如果输入字符串长度超过127(因为要留位置存\0),会被截断;如果输入长度小于128,strncpy不会自动添加字符串结束符\0,后续strlen(temp)会读到栈里的垃圾数据,导致越界操作。
3. 返回std::string的c_str()指针
std::string temp是函数内的局部对象,函数结束时它会被自动析构,此时temp.c_str()返回的指针指向的内存已经被释放了。你返回这个指针给外部,外部调用时访问的是无效内存,自然得不到正确结果。
正确的实现方式
推荐:C++风格(用std::string)
这是最符合C++11及以后标准的写法,安全且不需要手动管理内存:
#include <string> #include <iostream> std::string encode(const std::string& input) { std::string result = input; // 范围for循环遍历每个字符并异或 for (char& c : result) { c ^= 0xA; } return result; } int main() { std::string original = "Hello World!"; std::string encoded = encode(original); std::string decoded = encode(encoded); // 异或两次即可还原原字符串 std::cout << "还原后的字符串:" << decoded << std::endl; return 0; }
这里直接返回std::string对象,C会自动处理内存的拷贝(C11及以上会用移动语义,效率更高),外部拿到的是完整有效的字符串,完全不会有野指针或内存访问的问题。
可选:安全的C风格实现
如果你一定要用C风格的指针,需要用动态分配内存(堆内存),同时记得手动释放:
#include <cstring> #include <cstdio> char* encode(const char* input) { size_t str_len = strlen(input); // 动态分配内存,+1是为了存储字符串结束符'\0' char* result = new char[str_len + 1]; // 拷贝原字符串到新内存 strcpy(result, input); for (size_t i = 0; i < str_len; ++i) { result[i] ^= 0xA; } return result; } int main() { const char* original = "Hello World!"; char* encoded = encode(original); char* decoded = encode(encoded); printf("还原后的字符串:%s\n", decoded); // 必须释放动态分配的内存,避免内存泄漏 delete[] encoded; delete[] decoded; return 0; }
注意:用new分配的内存一定要用delete[]释放(因为是数组),否则会造成内存泄漏。
内容的提问来源于stack exchange,提问作者alive-and-well

