Char Pointer Segmentation Fault
好的,这是正在发生的事情的要点:
我将字符数组
1 2 |
这就是我以前一直使用该功能的方式:
1 2 | char *name ="HEY"; Function(name); |
这是我错误地利用它的方式:
1 2 | char name[3] ="HEY"; Function(name); |
与上述相同的语句,它可以正常工作。通过将名称更改为恒定的" HEY"(具有相同的输入),一切顺利进行,我确保没有其他问题。
如果有人能想到一个原因,我将非常感谢您的帮助。谢谢!
这是完整的功能:
- openList是指向结构的链表开头的指针
- tempOpen是一个临时指针,我们可以用来浏览列表,而无需更改openList的位置
- findOpenSetSID / findItem->通过SID /键在链接列表中查找结构
- answerOpen / answerItem-> 1 ==第一个节点,2 ==任何其他节点,0 =找不到
这是所涉及结构的简要说明。
开放结构是指向另一个结构(称为集合结构)的指针的链接列表。
集合结构是名称,sid和项结构的链接列表
项目结构是数据和键的链接列表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | Error_t WRITE(Sid_t sid, char *key, char *data){ Open_p_t tempOpen = openList; //setting a pointer to a struct int answerOpen = findOpenSetSID(sid, &tempOpen); if(answerOpen > 0){ Set_p_t targetNode; if(answerOpen == 1){ targetNode = tempOpen->file; } else{ targetNode= tempOpen->next->file; } Item_p_t tempItem = targetNode->items; int answerItem = findItem(key, &tempItem); Item_p_t targetItem; targetItem = (Item_p_t)malloc(sizeof(Item_t)); if(answerItem > 0){ if(answerItem == 1){ targetItem = targetNode->items; } else{ targetItem = targetNode->items->next; } targetItem->data = data; } else{ **targetItem->data = data;** <<<The problem line. basically I am just adding items to my sets. But this line freaks out when the input changes from char* to char[] targetItem->key = key; targetItem->next = targetNode->items; targetNode->items = targetItem; } return 0; } return 1; } |
这是输入段:
then calls WRITE(setId, key, data);
首先,这两行:
1 2 |
最上面一行没有用,会导致内存泄漏。
其次,这两行:
1 2 | char *name ="HEY"; char name[3] ="HEY"; |
接近但不完全相同。第一个结果导致
如果您的函数假定它正在获取一个以空值结尾的字符串(很有可能),则第二个变量可能会导致段错误。
因此,让我们从头开始。您从文件中读取密钥,字符串数据对。您可以按照阅读顺序来建立这些对的链接列表。那呢
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 | /* compile with: gcc -std=c89 -pedantic -Wall -O2 -o so_10185705 so_10185705.c test with: valgrind ./so_10185705 */ #include <stdlib.h> #include <string.h> #include <stdio.h> struct node_t { char key[32]; char value[64]; struct node_t *next; }; static void print_list(const struct node_t *curr) { while (curr) { printf("%s, %s ", curr->key, curr->value); curr = curr->next; } } static void free_list(struct node_t **currp) { struct node_t *curr = *currp; *currp = NULL; /* don't leave dangling pointers */ while (curr) { struct node_t *next = curr->next; curr->next = NULL; free((void *)curr); curr = next; } } /* O(n) but useful */ static const struct node_t * find_in_list(const struct node_t *curr, const char *key) { while (curr) { if (!strncmp(curr->key, key, sizeof(curr->key))) return curr; curr = curr->next; } return NULL; } /* Same as find_in_list but less useful */ static int is_in_list(const struct node_t *curr, const char *key) { while (curr) { if (!strncmp(curr->key, key, sizeof(curr->key))) return 1; curr = curr->next; } return 0; } int main() { struct node_t *head = NULL; FILE *f = fopen("foo","r"); if (!f) exit(1); while (!feof(f)) { struct node_t *new_node = malloc(sizeof(struct node_t)); fscanf(f,"%s %s", new_node->key, new_node->value); new_node->next = head; head = new_node; } fclose(f); print_list(head); const struct node_t *node = find_in_list(head,"abcd2"); if (node) { printf("found! key = %s, value = %s ", node->key, node->value); } else { printf("not found! "); } if (is_in_list(head,"abcd3")) { printf("found key in list but now I don't know the value associated with this key. "); } else { printf("not found! "); } free_list(&head); return 0; } /* explanation of bugs in OP's code */ struct node_t_2 { char *key; char *value; struct node_t_2 *next; }; void build_list(FILE *f, struct node_t_2 *curr) { while (!feof(f)) { /* These variable are allocated on the stack. Their lifetime is limited to the current scope. At the closing curly brace of the block in which they are declared, they die, the information in them is lost and pointer to them become invalid garbage. */ key char[32]; value char[64]; /* Of course, you can only read keys up to 31 bytes long and values up to 63 bytes long. Because you need an extra byte for the string's NUL terminator. fscanf puts that NUL terminator for you. If it didn't, you would not be able to use the data: you would not know the lenth of the string. If you need 32-byte long keys, declare the variable key to be 33 bytes long. */ fscanf(f,"%s %s", key, value); /* You can use key and value here */ struct node_t_2 bad_new_node; /* You cannot add bad_new_node to the list, because as soon as you reach '}' it will die. You need a place for the node that will not disappear (be reused on the next iteration of the loop). So it must be on the heap. How many bytes do you need for the node? Enough to hold the three pointers: 12 bytes on 32bit, 24 bytes on 64bit. The compiler knows how many bytes a struct needs. */ struct node_t_2 *new_node = malloc(sizeof(struct node_t_2)); /* You can add new_node to the list, because it is on the heap and will exist until either passed to free() or the process (program) exits. */ new_node->key = key; new_node->value = value; /* That was a bug, because we stored pointers to garbage. Now new_node has a pointer to a place that will cease to exist as soon as we reach '}'. */ new_node->key = strdup(key); new_node->value = strdup(value); /* strdup is a standard function that can be implemented like this: char * strdup(const char *s) { int len = strlen(s) char *p = malloc(len); memcpy(p, s, len); return p; } Now new_node has pointers to memory on the heap that will continue to exist until passed to free or the process terminates. */ new_node->next = curr; curr = new_node; /* At the next line, memory for key and value is disappears and is re-used if we re-enter the loop. */ } } /* If your list nodes have pointers instead of arrays, you need to free the strings pointed to by those pointers manually, becuause freeing the list node wont free stuff it points to. */ free_list(struct node_t_2 **currp) { struct node_t_2 *curr = *currp; *currp = NULL; while (curr) { struct node_t_2 *next = curr->next; free((void *)curr->key); curr->key = NULL; free((void *)curr->value); curr->value = NULL; curr->next = NULL; free((void *)curr); curr = next; } } |
从片段中不确定如何声明
1 |
由于char的大小只有一个字节,并且取决于要存储的内容,因此您需要一个用于完整指针的空间(4或8个字节),或者如果您希望将内容复制到分配的空间中,则需要一个char序列。
所以
1 |
要么
1 |