C++ 为什么此指针复制不正确?为什么分段错误没有提前发生?
我正在调试一个程序,该程序从二进制文件读取数据并将其放入C++ 为什么此指针复制不正确?为什么分段错误没有提前发生?,c++,pointers,constructor,gdb,initialization,C++,Pointers,Constructor,Gdb,Initialization,我正在调试一个程序,该程序从二进制文件读取数据并将其放入TaggerDataUnigram对象的字段中,TaggerDataUnigram是从TaggerData派生的类。所有读取操作都读取文件中指定的大量数据对象,并将这些对象放入TaggerData字段中。因此,我定义了一个函数ReadForNumberToRead,该函数将文件和Reader*作为参数,Reader是定义如何从文件读取数据的functor的基类。每个读取器派生都将标记数据*作为参数,并将指针的值存储为成员。不幸的是,Tagg
TaggerDataUnigram
对象的字段中,TaggerDataUnigram
是从TaggerData
派生的类。所有读取操作都读取文件中指定的大量数据对象,并将这些对象放入TaggerData
字段中。因此,我定义了一个函数ReadForNumberToRead
,该函数将文件和Reader*
作为参数,Reader
是定义如何从文件读取数据的functor的基类。每个读取器
派生都将标记数据*
作为参数,并将指针的值存储为成员。不幸的是,TaggerData
使用getter和setter,但是getter返回对字段的引用。因此,例如,OpenClassReader
通过tagger\u data\u pointer->getOpenClass()
访问TaggerData::open\u class
示例:
禁止RuleReader
的构造函数:
ForbiddingRuleReader::ForbiddingRuleReader(
FILE*& tagger_data_input_file_reference,
TaggerData* tagger_data_pointer)
: Reader(tagger_data_input_file_reference, tagger_data_pointer) {}
ArrayTagReader::ArrayTagReader(FILE*& tagger_data_input_file_reference,
TaggerData* tagger_data_pointer)
: Reader(tagger_data_input_file_reference, tagger_data_pointer) {}
void TaggerDataUnigram::ReadTheForbiddingRules(
FILE*& unigram_tagger_data_input_file_reference) {
ForbiddingRuleReader forbidding_rule_reader(
unigram_tagger_data_input_file_reference,
this);
ReadForNumberToRead(unigram_tagger_data_input_file_reference,
&forbidding_rule_reader);
}
[. . .]
void TaggerDataUnigram::ReadTheArrayTags(
FILE*& unigram_tagger_data_input_file_reference) {
ArrayTagReader array_tag_reader(unigram_tagger_data_input_file_reference,
this);
ReadForNumberToRead(unigram_tagger_data_input_file_reference,
&array_tag_reader);
}
tagger\u data\u pointer\u
是受保护的读卡器的成员
。和ArrayTagrader的相同构造函数:
:
ForbiddingRuleReader::ForbiddingRuleReader(
FILE*& tagger_data_input_file_reference,
TaggerData* tagger_data_pointer)
: Reader(tagger_data_input_file_reference, tagger_data_pointer) {}
ArrayTagReader::ArrayTagReader(FILE*& tagger_data_input_file_reference,
TaggerData* tagger_data_pointer)
: Reader(tagger_data_input_file_reference, tagger_data_pointer) {}
void TaggerDataUnigram::ReadTheForbiddingRules(
FILE*& unigram_tagger_data_input_file_reference) {
ForbiddingRuleReader forbidding_rule_reader(
unigram_tagger_data_input_file_reference,
this);
ReadForNumberToRead(unigram_tagger_data_input_file_reference,
&forbidding_rule_reader);
}
[. . .]
void TaggerDataUnigram::ReadTheArrayTags(
FILE*& unigram_tagger_data_input_file_reference) {
ArrayTagReader array_tag_reader(unigram_tagger_data_input_file_reference,
this);
ReadForNumberToRead(unigram_tagger_data_input_file_reference,
&array_tag_reader);
}
它们的用法也一样:
ForbiddingRuleReader::ForbiddingRuleReader(
FILE*& tagger_data_input_file_reference,
TaggerData* tagger_data_pointer)
: Reader(tagger_data_input_file_reference, tagger_data_pointer) {}
ArrayTagReader::ArrayTagReader(FILE*& tagger_data_input_file_reference,
TaggerData* tagger_data_pointer)
: Reader(tagger_data_input_file_reference, tagger_data_pointer) {}
void TaggerDataUnigram::ReadTheForbiddingRules(
FILE*& unigram_tagger_data_input_file_reference) {
ForbiddingRuleReader forbidding_rule_reader(
unigram_tagger_data_input_file_reference,
this);
ReadForNumberToRead(unigram_tagger_data_input_file_reference,
&forbidding_rule_reader);
}
[. . .]
void TaggerDataUnigram::ReadTheArrayTags(
FILE*& unigram_tagger_data_input_file_reference) {
ArrayTagReader array_tag_reader(unigram_tagger_data_input_file_reference,
this);
ReadForNumberToRead(unigram_tagger_data_input_file_reference,
&array_tag_reader);
}
不用说,标记数据Unigram
对象没有超出范围。
OpenClassReader
和bankindingrulereader
都能完美地工作;它们将文件副本和TaggerData*
存储为字段,然后依次从文件中读取数据,并将其放入TaggerData
中相应的字段中。当构造阵列图读取器
时会出现问题。尽管与禁止规则读取器
共享相同的构造函数并以相同的方式使用,但还是出现了严重的问题--标记数据指针
没有指向与对象构造时使用的标记数据*标记数据指针
相同的内存位置强>
但是,在第一次调用TagIndexReader::operator()
时,程序会遇到分段错误,特别是SIGSEGV
。这并不奇怪;虽然TagIndexReader
的tagger\u data\u pointer\u
是有效的,但是TaggerDataUnigram
对象的很大一部分遭到破坏
Breakpoint 4, TagIndexReader::operator() (this=0x7fffffffd650) at tag_index_reader.cc:7
7 void TagIndexReader::operator()() {
(gdb) print tagger_data_pointer_
$16 = (TaggerData *) 0x7fffffffd8c0 <---------- This is the correct value.
(gdb) print *tagger_data_pointer_
$17 = {_vptr.TaggerData = 0x41e5b0 <vtable for TaggerDataUnigram+16>,
open_class = std::set with 6467592 elements<error reading variable: Cannot access memory at address 0x5200000051>,
更新:
不知何故,我错过了ArrayTagReader
中的tagger\u data\u poiner\u的声明;使指针const
产生编译器错误,引起我的注意。我仍然不明白的是为什么:
编译器没有抱怨使用了未初始化的指针
程序在尝试修改(例如,tagger\u data\u poiner\u->getArrayTags()
)时未遇到分段错误
尽管共享了相同的构造函数,并且使用了与禁止RuleReader相同的方式
我不知道为什么你认为这些是重要的,但是我可以告诉你,按照C++标准,这两个类型的内存布局是否相同,或者是否可以“代码> RealTytCase(或道德等价物),完全没有相关性。它们之间。
我无法正确地阅读您的代码,因为除了“更新”之外,所有内容都非常混乱,除了作者之外,任何人都很难阅读。更新部分似乎还可以。因此,我将顺便介绍一些使用指针复制的技巧(正如我最近看到的,许多人都会犯这些错误),也许这会有所帮助
确保您不仅仅是从一个未“标记”为已分配的内存位置进行复制。换句话说,如果您有一个指针,并且您只是将数组中的数据复制到它所指向的内存位置,那么没有任何东西可以阻止您的程序或计算机上当前运行的其他程序修改该区域。首先分配空间(使用new、malloc等),然后可以从中/向中复制
type*p=新类型[尺寸]代码>
即使您满足了第1点,也要确保复制的空间不超过大小
关于这个问题的建议,通过对它的评论(我不能评论)
你可能是一个非常好的程序员。但是你会犯错误的。意味着你必须找到他们。这意味着您应该保持代码整洁。但是保持整洁还有更重要的原因。阅读您的代码的人并不真正知道“应该”在哪里。对他们来说,阅读凌乱的代码是不可能完成的任务。这一点很重要,因为可能需要有人继续为公司编写代码。或者,如果你正在寻求其他程序员的帮助,就像你现在正在做的那样,你需要有人来帮助你
对于代码中的每个子块(用{}覆盖),缩进应该是1个制表符或4个空格(不能在StackOverflow上使用制表符),除非该块为空
如果一条指令由于长度原因在下一行继续执行,它也应该进行缩进。在这种情况下,您还可以添加额外的选项卡或空格,使一切看起来都很好。例如,如果您有一个足够长的方程,可以分成3行,则可以使每一行从第一行的“=”开始
“UPDATE”部分看起来比其他部分好得多,但是您仍然应该使用4-空格缩进而不是2-空格缩进。“tagger\u data\u指针
与对象构造时使用的TaggerData*tagger\u指针不指向内存中的同一位置”
这通常意味着该值已被覆盖。一个非常常见的原因是前一个字段中的缓冲区溢出,或者后一个字段中的_-under_流不太常见。这也解释了为什么这是一个问题,只发生在你的两个类之一;另一个班有其他的