char * 未从重载运算符或内存管理问题中正确返回
char * not returned correctly from overloaded operator or memory managment issue
我尝试读取一个文件,将其解压缩并将其解析为 C++ 中的树。一切正常,有一个例外:出于某种原因,我可以构造一个 char[] 字符串,并在它上面使用一个指针,在友好的重载 <<-operator 中的 cout 的帮助下输出它,但不能使用返回的指针运算符来计算字符串。我在想这可能与字符串内存的可见性有关,但这对我来说没有意义,因为 "new" 分配的内存应该对每个人可见,因为它在程序的堆上而不是某种对象或 class 堆。这一切听起来相当令人困惑,让我给你看一个精简版的源代码,我很确定一切都会变得清晰(可能是我这边的一些非常愚蠢的错误......但我试了两天但没有找到错误):
主要内容:
#include "dekompstream.h"
#include <iostream>
int main(void) {
char *testString;
DekompStream ds(nullptr, 0);
std::cout << "TEST" << std::endl;
testString << ds;
std::cout << "Outside operator: " << testString << std::endl; // Fails misarably. Some weird randome memory-slice looking output
//delete [] testString;
return 0;
}
dekompstream.cpp:
#include "dekompstream.h"
DekompStream::DekompStream(uint8_t *kompDaten, unsigned int anzahlBytes) {
}
DekompStream::~DekompStream() {
}
uint8_t *DekompStream::dekompremieren() {
char *test = new char[4];
test[0] = 'A';
test[1] = 'B';
test[2] = 'C';
test[3] = '[=11=]';
return (uint8_t *)test;
}
char *operator<<(char *zeichenkette, DekompStream &dekompStream) {
zeichenkette = (char *)dekompStream.dekompremieren();
std::cout << "Inside operator: " << zeichenkette << std::endl; // Works fine
return zeichenkette;
}
dekompstream.h:
#ifndef DEKOMPSTREAM_H
#define DEKOMPSTREAM_H
#include <cstdint>
#include <iostream>
class DekompStream {
public:
DekompStream(uint8_t *kompDaten, unsigned int anzahlBytes);
~DekompStream(void);
friend char *operator<<(char *zeichenkette, DekompStream &dekompStream);
private:
uint8_t *dekompremieren();
};
#endif
提前致谢:-)
testString << ds
并不像您想象的那样。
如果我们看一下 operator<<
的代码:
char *operator<<(char *zeichenkette, DekompStream &dekompStream) {
zeichenkette = (char *)dekompStream.dekompremieren();
return zeichenkette;
}
函数将 char*
参数重新分配给新值,然后 returns 新值。美好的。好的。但是编译器如何使用它呢?
当我们写:
testString << ds;
编译器将其转化为:
operator<<(testString, ds);
看到错误了吗?
您返回了一个新值,但由于运算符重载变成了函数调用,分配的指针丢失了。此外,因为 char*
参数被简单地重新分配,原始指针值没有改变,这意味着你得到了之前堆栈上的任何东西。
如果我们查看 iostream 的 STL 函数声明,我们将找到修复它的方法:
ostream& operator<< (ostream& os, const char* s);
请注意,第一个参数是通过引用传递的 - 这可确保函数对流所做的任何修改都保留在调用上下文中。
只需将您的函数定义更改为:
char *operator<<(char *&zeichenkette, DekompStream &dekompStream){
...
}
问题就会消失。
我尝试读取一个文件,将其解压缩并将其解析为 C++ 中的树。一切正常,有一个例外:出于某种原因,我可以构造一个 char[] 字符串,并在它上面使用一个指针,在友好的重载 <<-operator 中的 cout 的帮助下输出它,但不能使用返回的指针运算符来计算字符串。我在想这可能与字符串内存的可见性有关,但这对我来说没有意义,因为 "new" 分配的内存应该对每个人可见,因为它在程序的堆上而不是某种对象或 class 堆。这一切听起来相当令人困惑,让我给你看一个精简版的源代码,我很确定一切都会变得清晰(可能是我这边的一些非常愚蠢的错误......但我试了两天但没有找到错误):
主要内容:
#include "dekompstream.h"
#include <iostream>
int main(void) {
char *testString;
DekompStream ds(nullptr, 0);
std::cout << "TEST" << std::endl;
testString << ds;
std::cout << "Outside operator: " << testString << std::endl; // Fails misarably. Some weird randome memory-slice looking output
//delete [] testString;
return 0;
}
dekompstream.cpp:
#include "dekompstream.h"
DekompStream::DekompStream(uint8_t *kompDaten, unsigned int anzahlBytes) {
}
DekompStream::~DekompStream() {
}
uint8_t *DekompStream::dekompremieren() {
char *test = new char[4];
test[0] = 'A';
test[1] = 'B';
test[2] = 'C';
test[3] = '[=11=]';
return (uint8_t *)test;
}
char *operator<<(char *zeichenkette, DekompStream &dekompStream) {
zeichenkette = (char *)dekompStream.dekompremieren();
std::cout << "Inside operator: " << zeichenkette << std::endl; // Works fine
return zeichenkette;
}
dekompstream.h:
#ifndef DEKOMPSTREAM_H
#define DEKOMPSTREAM_H
#include <cstdint>
#include <iostream>
class DekompStream {
public:
DekompStream(uint8_t *kompDaten, unsigned int anzahlBytes);
~DekompStream(void);
friend char *operator<<(char *zeichenkette, DekompStream &dekompStream);
private:
uint8_t *dekompremieren();
};
#endif
提前致谢:-)
testString << ds
并不像您想象的那样。
如果我们看一下 operator<<
的代码:
char *operator<<(char *zeichenkette, DekompStream &dekompStream) {
zeichenkette = (char *)dekompStream.dekompremieren();
return zeichenkette;
}
函数将 char*
参数重新分配给新值,然后 returns 新值。美好的。好的。但是编译器如何使用它呢?
当我们写:
testString << ds;
编译器将其转化为:
operator<<(testString, ds);
看到错误了吗?
您返回了一个新值,但由于运算符重载变成了函数调用,分配的指针丢失了。此外,因为 char*
参数被简单地重新分配,原始指针值没有改变,这意味着你得到了之前堆栈上的任何东西。
如果我们查看 iostream 的 STL 函数声明,我们将找到修复它的方法:
ostream& operator<< (ostream& os, const char* s);
请注意,第一个参数是通过引用传递的 - 这可确保函数对流所做的任何修改都保留在调用上下文中。
只需将您的函数定义更改为:
char *operator<<(char *&zeichenkette, DekompStream &dekompStream){
...
}
问题就会消失。