C++技术问题:向结构体的双指针数组插入指针时出现段错误
Hey there, let's break down why you're hitting that segmentation fault and how to fix it properly, especially since you need dynamic child node counts.
The Root Cause: Wrong Initialization of the Child Array
Your core issue is that you never actually allocated memory for the children pointer array. When you do node1->children = &node2;, all you're doing is making the TreeNode** children pointer point to the address of the single node2 pointer—not a proper array that can hold multiple pointers.
Think about it: &node2 is a single TreeNode* address. Assigning that to children means children[0] points to node2, but children[1], children[2], etc., are accessing memory that isn't yours to use. That's an illegal memory access, which is exactly why you get a segfault when you try to assign node1->children[2] = node4;.
Also, you initialized node1 with num_children = 0 but never updated that value, which adds to the logical confusion here.
Solutions: Dynamically Managing the Child Array
Since you need the number of children to change at runtime, here are two solid approaches:
Option 1: Manual Dynamic Array Management (C-Style)
If you want to handle memory yourself, you'll need to track both the current number of children and the capacity of your array, then resize it when needed:
- Add a
capacityfield to yourTreeNodeto track how many pointers the array can hold. - When adding a child, if the number of children hits the capacity, resize the array (usually double it to avoid frequent reallocations), copy the old elements over, and free the old array.
- Always add new children to the next available index and increment
num_children.
Here's modified code to show this:
#include <iostream> #include <cstring> using namespace std; typedef struct TreeNode { int key; int val; bool flag; int num_children; int capacity; // Tracks how many child pointers we can hold TreeNode **children; } TreeNode; // Helper function to safely add a child node void addChild(TreeNode* parent, TreeNode* child) { // Resize if we've hit capacity if (parent->num_children == parent->capacity) { int new_capacity = parent->capacity == 0 ? 2 : parent->capacity * 2; TreeNode** new_children = new TreeNode*[new_capacity]; // Copy existing children to the new array memcpy(new_children, parent->children, parent->num_children * sizeof(TreeNode*)); // Clean up old array delete[] parent->children; parent->children = new_children; parent->capacity = new_capacity; } // Add the new child and increment count parent->children[parent->num_children] = child; parent->num_children++; } int main() { TreeNode* node1 = new TreeNode{1, 1, true, 0, 0, NULL}; TreeNode* node2 = new TreeNode{2, 2, true, 0, 0, NULL}; TreeNode* node3 = new TreeNode{3, 2, true, 0, 0, NULL}; TreeNode* node4 = new TreeNode{4, 2, true, 0, 0, NULL}; TreeNode* node5 = new TreeNode{5, 2, true, 0, 0, NULL}; addChild(node1, node2); cout << "Added node2 as child of node1;" << endl; addChild(node1, node3); cout << "Added node3 as child of node1;" << endl; addChild(node1, node4); cout << "Added node4 as child of node1;" << endl; addChild(node1, node5); cout << "Added node5 as child of node1;" << endl; // Don't forget to free all allocated memory in a real program! return 0; }
Option 2: Use C++ STL vector<TreeNode*> (Simpler & Safer)
If you don't want to deal with manual memory management, using a vector is the way to go—it handles resizing and memory cleanup automatically. Just replace your TreeNode** children with a vector<TreeNode*>:
Modified TreeNode struct:
#include <iostream> #include <vector> using namespace std; typedef struct TreeNode { int key; int val; bool flag; vector<TreeNode*> children; // Replace the double pointer with a vector } TreeNode;
Adding children becomes trivial:
int main() { TreeNode* node1 = new TreeNode{1, 1, true, {}}; TreeNode* node2 = new TreeNode{2, 2, true, {}}; TreeNode* node3 = new TreeNode{3, 2, true, {}}; TreeNode* node4 = new TreeNode{4, 2, true, {}}; TreeNode* node5 = new TreeNode{5, 2, true, {}}; node1->children.push_back(node2); cout << "Added node2 as child of node1;" << endl; node1->children.push_back(node3); cout << "Added node3 as child of node1;" << endl; node1->children.push_back(node4); cout << "Added node4 as child of node1;" << endl; node1->children.push_back(node5); cout << "Added node5 as child of node1;" << endl; // Remember to free all nodes in a real program: iterate through vectors and delete each child first! return 0; }
This approach eliminates the risk of segfaults from array out-of-bounds access and takes care of all the low-level memory work for you—it's the recommended approach in modern C++.
Quick Note on Memory Cleanup
Whichever method you choose, make sure to properly free all dynamically allocated memory at the end of your program to avoid memory leaks. For the vector approach, you'll need to loop through each node's children vector, delete each child, then delete the parent node itself.
内容的提问来源于stack exchange,提问作者Adam Lee

