C++类成员函数中指针值意外变为0x1的问题排查及优化建议问询
Let's break down what's happening here and walk through practical fixes and debugging steps for your pointer corruption issue. That 0x1 value popping up is a classic red flag for memory corruption—most often tied to invalidated iterators or stack overwrites, so let's dig in.
First, let's recap your code and output for clarity:
std::cout << "The pointer value is " << *op_itr << std::endl; candidates_.erase(op_itr); std::cout << "The pointer value is " << *op_itr << std::endl; schedule_operation(*op_itr); std::cout << "The pointer value is " << *op_itr << std::endl; schedulable_op_ = *op_itr; std::cout << "The pointer value is " << *op_itr << std::endl;Output:
The pointer value is 0x555555695650 The pointer value is 0x555555695650 The pointer value is 0x1
The Root Cause Clues
1. You're Using an Invalidated Iterator
The biggest mistake here is dereferencing op_itr after calling candidates_.erase(op_itr). Depending on what type candidates_ is:
- For
std::vector/std::unordered_set, erasing an iterator invalidates it completely—you can't safely use it again. - For
std::list/std::set, erase returns a valid iterator to the next element, but your code doesn't capture that.
The second cout working is pure luck—your program is accessing memory that's no longer owned by the container. When schedule_operation runs, it's likely overwriting that now-unowned memory, turning the pointer to 0x1.
2. Stack Corruption Inside schedule_operation
That 0x1 value is a common sign of stack smashing. This could happen if:
schedule_operationwrites past the end of a local array or buffer.- It casts the
mlir::Operation*incorrectly and modifies unrelated memory. - It accesses a dangling pointer to a stack-allocated object, corrupting the stack frame.
The stack corruption is overwriting the memory location where your invalid iterator is pointing—hence the sudden jump to 0x1.
Immediate Fixes & Debugging Steps
Step 1: Fix the Iterator Invalidation First
This is the low-hanging fruit—stop using invalidated iterators. Store the pointer before erasing, then use that stored value instead:
// Store the pointer while the iterator is still valid mlir::Operation* op = *op_itr; candidates_.erase(op_itr); // Now use the stored pointer instead of the invalid iterator std::cout << "The pointer value is " << op << std::endl; schedule_operation(op); std::cout << "The pointer value is " << op << std::endl; schedulable_op_ = op; std::cout << "The pointer value is " << op << std::endl;
This eliminates the undefined behavior of dereferencing an invalid iterator, which might fix the issue immediately or make the corruption more predictable.
Step 2: Use Sanitizers to Catch Corruption Early
Compilers have built-in tools to pinpoint memory issues:
- Compile your code with
-fsanitize=address(GCC/Clang) to enable AddressSanitizer. It will detect stack overflows, use-after-free, and out-of-bounds writes, giving you a precise stack trace of where the corruption starts. - If you're working with MLIR, make sure you build MLIR with sanitizers enabled too—corruption could be happening inside MLIR's internal operations.
Step 3: Audit schedule_operation and Lifetime Management
- Step through
schedule_operationwith a debugger. Check for any local arrays being written beyond their size, or pointers being cast to incorrect types. - Verify that
mlir::Operation*instances aren't being deleted or deallocated elsewhere while yourScheduleclass holds references to them. MLIR operations are usually managed by the IR context, so manual deletion can cause chaos. - Consider using MLIR's own
OperationPtror standard smart pointers likestd::shared_ptrto manage ownership of operations—this prevents dangling pointers by design.
Why Removing the Last cout "Fixes" It?
That's classic undefined behavior. Adding or removing a cout changes the stack layout, shifting where the invalid iterator's memory is stored. The corruption from schedule_operation simply stops hitting that location—it's not a fix, just a coincidence that masks the real problem.
内容的提问来源于stack exchange,提问作者brewdogNA

