win&linux 在同一个有关问题下的不同表现
我在写单链表的逆转时,遇到了一些很有意思的事情。
同样一段代码,在 win 和 linux 下是完全两种不同的结果。
#include <stdio.h> #include <stdlib.h> #include <string.h> #define SIZE 64 typedef struct info{ int num; char msg[SIZE]; struct info *next; }Info; typedef struct vec{ Info *element; struct vec *next; }Vector; const unsigned int SIZE_INFO = sizeof(Info); Info *createInfo(Info *header, int nums) { int num = 0; char *msg = "hello msg"; Info *tmp = NULL; Info *h2 = header; int i = 0; #define NUM 4 char strNum[NUM]; memset(strNum, 0x00, NUM); header->num = 0; for (i = 0; i < nums; i++) { tmp = (Info *)calloc(SIZE_INFO, 1); tmp->num = num++; strcpy(tmp->msg, msg); sprintf(strNum, ": %d", tmp->num); strcat(tmp->msg, strNum); h2->next = tmp; h2 = h2->next; h2->next = NULL; header->num++; memset(strNum, 0x00, NUM); } return header; } void deleteInfo(Info *header) { Info *tmp = header->next; Info *tmp2 = NULL; while(tmp != NULL) { tmp2 = tmp->next; free(tmp); tmp = tmp2; } header->next = NULL; } void printInfo(const Info *header) { Info *tmp = header->next; while (tmp != NULL) { printf("[num]->%d\t[msg]->%s\n", tmp->num, tmp->msg); tmp = tmp->next; } printf("**END**\n"); } Info *reserve(Info *header) { Info *tail = NULL; Info *tmp = NULL; Vector *v = (Vector *)calloc(sizeof(Vector), 1); v->next = NULL; Vector *vTmp = NULL; tmp = header; while(tmp->next != NULL) { tmp = tmp->next; vTmp = (Vector *)calloc(sizeof(Vector), 1); vTmp->element = tmp; if (v->next == NULL) { v->next = vTmp; vTmp->next = NULL; } else { vTmp->next = v->next; v->next = vTmp; } } vTmp = v; tmp = header; while (vTmp->next != NULL) { tmp->next = vTmp->next->element; vTmp = vTmp->next; tmp = tmp->next; } tmp->next = NULL; vTmp = v->next; Vector *vTmp2 = NULL; while (vTmp != NULL) { vTmp2 = vTmp->next; free(vTmp); vTmp = vTmp2; } vTmp = NULL; free(v); v = NULL; return header; } void re(Info *header, Info *cur) { if (cur->next == NULL) { header->next = cur; cur->next = NULL; } else { Info *a = NULL; Info *b = NULL; if (header == cur) { a = cur->next; b = a->next; } else { a = cur; b = cur->next; } if (b != NULL) { re(header, b); b->next = a; if (cur == header) a->next = NULL; } } } int main(int argc, char *argv[]) { Info *header = (Info *)calloc(SIZE_INFO, 1); int num; if (argc == 1) num = 11; else sscanf(argv[1], "%d", &num); header = createInfo(header, num); printInfo(header); // header = reserve(header); // printInfo(header); //reserve3(header, header); re(header, header); printInfo(header); deleteInfo(header); free(header); header = NULL; // linux 下注释掉 //system("pause"); return EXIT_SUCCESS; }
这里有个很好玩的东西,开始我是在 linux 下运行的,当我把链表建的超过 10 时,得到的数据量就会非常的大,比如说 11 时,就会得到 100 个数据, 111 就会得到 10000 个数据。
然而我到 winxp 下一运行就报错了:
[Run-Time Check Failure #2 - Stack around the variable 'strNum' was corrupted.]
确实问题就出现在, createInfo 方法里的 strNum 这个字符数组的大小的设定上。
在使用: sprintf(strNum, ": %d" , tmp->num);
时,出现了一个问题。开始如果设定的链表数是 1 位数时,那么此处 strNum 中前 3 个字节有 值,第四个字节可以正常的以 ’ \0 ’ 结尾,但是在存储 10 时,它在转换成字符之后,就应该是两个单独的字符,应此就占了 2 字节。此时 strNum 总共的 4 个字节就都用完了,那么正常的字符串结尾的 ’ \0 ’ 就不见了,此时就出现了 win 和 linux 下两者不同的出错处理。此处, linux 下的给我创建 100 个数据,我就表示很怀疑了,这是为什么呢?看来 win 的编译器还是挺严格的,这里只是说, strNum 的堆栈被破坏了,但是 strNum 中的数据是对的,就给报了个 run-time error, 而不会像 linux 下一样,竟然跑出个匪夷所思的结果。不知道是不是我的 gcc 版本太旧了?
还有一个有意思的地方是: win 在报这个 run-time error 时,是在函数 createInfo 结束时,即 createInfo 退栈时出的错,也就是说在释放 strNum 的内存时发现 strNum 的 stack was corrupted?
当然,如果在createInfo中将strNum的大小设的足够大的话,这个问题也是不会出现的。
附上 linux 下创建 22 个数据的结果:
$ ./Info3 22 [num]->0 [msg]->hello msg: 0 [num]->1 [msg]->hello msg: 1 [num]->2 [msg]->hello msg: 2 [num]->3 [msg]->hello msg: 3 [num]->4 [msg]->hello msg: 4 [num]->5 [msg]->hello msg: 5 [num]->6 [msg]->hello msg: 6 [num]->7 [msg]->hello msg: 7 [num]->8 [msg]->hello msg: 8 [num]->9 [msg]->hello msg: 9 [num]->10 [msg]->hello msg: 10 [num]->11 [msg]->hello msg: 11 [num]->12 [msg]->hello msg: 12 [num]->13 [msg]->hello msg: 13 [num]->14 [msg]->hello msg: 14 [num]->15 [msg]->hello msg: 15 [num]->16 [msg]->hello msg: 16 [num]->17 [msg]->hello msg: 17 [num]->18 [msg]->hello msg: 18 [num]->19 [msg]->hello msg: 19 [num]->20 [msg]->hello msg: 20 [num]->21 [msg]->hello msg: 21 [num]->22 [msg]->hello msg: 22 [num]->23 [msg]->hello msg: 23 [num]->24 [msg]->hello msg: 24 [num]->25 [msg]->hello msg: 25 [num]->26 [msg]->hello msg: 26 [num]->27 [msg]->hello msg: 27 [num]->28 [msg]->hello msg: 28 [num]->29 [msg]->hello msg: 29 [num]->30 [msg]->hello msg: 30 [num]->31 [msg]->hello msg: 31 [num]->32 [msg]->hello msg: 32 [num]->33 [msg]->hello msg: 33 [num]->34 [msg]->hello msg: 34 [num]->35 [msg]->hello msg: 35 [num]->36 [msg]->hello msg: 36 [num]->37 [msg]->hello msg: 37 [num]->38 [msg]->hello msg: 38 [num]->39 [msg]->hello msg: 39 [num]->40 [msg]->hello msg: 40 [num]->41 [msg]->hello msg: 41 [num]->42 [msg]->hello msg: 42 [num]->43 [msg]->hello msg: 43 [num]->44 [msg]->hello msg: 44 [num]->45 [msg]->hello msg: 45 [num]->46 [msg]->hello msg: 46 [num]->47 [msg]->hello msg: 47 [num]->48 [msg]->hello msg: 48 [num]->49 [msg]->hello msg: 49 [num]->50 [msg]->hello msg: 50 [num]->51 [msg]->hello msg: 51 [num]->52 [msg]->hello msg: 52 [num]->53 [msg]->hello msg: 53 [num]->54 [msg]->hello msg: 54 [num]->55 [msg]->hello msg: 55 [num]->56 [msg]->hello msg: 56 [num]->57 [msg]->hello msg: 57 [num]->58 [msg]->hello msg: 58 [num]->59 [msg]->hello msg: 59 [num]->60 [msg]->hello msg: 60 [num]->61 [msg]->hello msg: 61 [num]->62 [msg]->hello msg: 62 [num]->63 [msg]->hello msg: 63 [num]->64 [msg]->hello msg: 64 [num]->65 [msg]->hello msg: 65 [num]->66 [msg]->hello msg: 66 [num]->67 [msg]->hello msg: 67 [num]->68 [msg]->hello msg: 68 [num]->69 [msg]->hello msg: 69 [num]->70 [msg]->hello msg: 70 [num]->71 [msg]->hello msg: 71 [num]->72 [msg]->hello msg: 72 [num]->73 [msg]->hello msg: 73 [num]->74 [msg]->hello msg: 74 [num]->75 [msg]->hello msg: 75 [num]->76 [msg]->hello msg: 76 [num]->77 [msg]->hello msg: 77 [num]->78 [msg]->hello msg: 78 [num]->79 [msg]->hello msg: 79 [num]->80 [msg]->hello msg: 80 [num]->81 [msg]->hello msg: 81 [num]->82 [msg]->hello msg: 82 [num]->83 [msg]->hello msg: 83 [num]->84 [msg]->hello msg: 84 [num]->85 [msg]->hello msg: 85 [num]->86 [msg]->hello msg: 86 [num]->87 [msg]->hello msg: 87 [num]->88 [msg]->hello msg: 88 [num]->89 [msg]->hello msg: 89 [num]->90 [msg]->hello msg: 90 [num]->91 [msg]->hello msg: 91 [num]->92 [msg]->hello msg: 92 [num]->93 [msg]->hello msg: 93 [num]->94 [msg]->hello msg: 94 [num]->95 [msg]->hello msg: 95 [num]->96 [msg]->hello msg: 96 [num]->97 [msg]->hello msg: 97 [num]->98 [msg]->hello msg: 98 [num]->99 [msg]->hello msg: 99 [num]->100 [msg]->hello msg: 100 **END** [num]->100 [msg]->hello msg: 100 [num]->99 [msg]->hello msg: 99 [num]->98 [msg]->hello msg: 98 [num]->97 [msg]->hello msg: 97 [num]->96 [msg]->hello msg: 96 [num]->95 [msg]->hello msg: 95 [num]->94 [msg]->hello msg: 94 [num]->93 [msg]->hello msg: 93 [num]->92 [msg]->hello msg: 92 [num]->91 [msg]->hello msg: 91 [num]->90 [msg]->hello msg: 90 [num]->89 [msg]->hello msg: 89 [num]->88 [msg]->hello msg: 88 [num]->87 [msg]->hello msg: 87 [num]->86 [msg]->hello msg: 86 [num]->85 [msg]->hello msg: 85 [num]->84 [msg]->hello msg: 84 [num]->83 [msg]->hello msg: 83 [num]->82 [msg]->hello msg: 82 [num]->81 [msg]->hello msg: 81 [num]->80 [msg]->hello msg: 80 [num]->79 [msg]->hello msg: 79 [num]->78 [msg]->hello msg: 78 [num]->77 [msg]->hello msg: 77 [num]->76 [msg]->hello msg: 76 [num]->75 [msg]->hello msg: 75 [num]->74 [msg]->hello msg: 74 [num]->73 [msg]->hello msg: 73 [num]->72 [msg]->hello msg: 72 [num]->71 [msg]->hello msg: 71 [num]->70 [msg]->hello msg: 70 [num]->69 [msg]->hello msg: 69 [num]->68 [msg]->hello msg: 68 [num]->67 [msg]->hello msg: 67 [num]->66 [msg]->hello msg: 66 [num]->65 [msg]->hello msg: 65 [num]->64 [msg]->hello msg: 64 [num]->63 [msg]->hello msg: 63 [num]->62 [msg]->hello msg: 62 [num]->61 [msg]->hello msg: 61 [num]->60 [msg]->hello msg: 60 [num]->59 [msg]->hello msg: 59 [num]->58 [msg]->hello msg: 58 [num]->57 [msg]->hello msg: 57 [num]->56 [msg]->hello msg: 56 [num]->55 [msg]->hello msg: 55 [num]->54 [msg]->hello msg: 54 [num]->53 [msg]->hello msg: 53 [num]->52 [msg]->hello msg: 52 [num]->51 [msg]->hello msg: 51 [num]->50 [msg]->hello msg: 50 [num]->49 [msg]->hello msg: 49 [num]->48 [msg]->hello msg: 48 [num]->47 [msg]->hello msg: 47 [num]->46 [msg]->hello msg: 46 [num]->45 [msg]->hello msg: 45 [num]->44 [msg]->hello msg: 44 [num]->43 [msg]->hello msg: 43 [num]->42 [msg]->hello msg: 42 [num]->41 [msg]->hello msg: 41 [num]->40 [msg]->hello msg: 40 [num]->39 [msg]->hello msg: 39 [num]->38 [msg]->hello msg: 38 [num]->37 [msg]->hello msg: 37 [num]->36 [msg]->hello msg: 36 [num]->35 [msg]->hello msg: 35 [num]->34 [msg]->hello msg: 34 [num]->33 [msg]->hello msg: 33 [num]->32 [msg]->hello msg: 32 [num]->31 [msg]->hello msg: 31 [num]->30 [msg]->hello msg: 30 [num]->29 [msg]->hello msg: 29 [num]->28 [msg]->hello msg: 28 [num]->27 [msg]->hello msg: 27 [num]->26 [msg]->hello msg: 26 [num]->25 [msg]->hello msg: 25 [num]->24 [msg]->hello msg: 24 [num]->23 [msg]->hello msg: 23 [num]->22 [msg]->hello msg: 22 [num]->21 [msg]->hello msg: 21 [num]->20 [msg]->hello msg: 20 [num]->19 [msg]->hello msg: 19 [num]->18 [msg]->hello msg: 18 [num]->17 [msg]->hello msg: 17 [num]->16 [msg]->hello msg: 16 [num]->15 [msg]->hello msg: 15 [num]->14 [msg]->hello msg: 14 [num]->13 [msg]->hello msg: 13 [num]->12 [msg]->hello msg: 12 [num]->11 [msg]->hello msg: 11 [num]->10 [msg]->hello msg: 10 [num]->9 [msg]->hello msg: 9 [num]->8 [msg]->hello msg: 8 [num]->7 [msg]->hello msg: 7 [num]->6 [msg]->hello msg: 6 [num]->5 [msg]->hello msg: 5 [num]->4 [msg]->hello msg: 4 [num]->3 [msg]->hello msg: 3 [num]->2 [msg]->hello msg: 2 [num]->1 [msg]->hello msg: 1 [num]->0 [msg]->hello msg: 0 **END**
这个结果是不是非常的牛叉。
附上linux&gcc相关信息:
1.$ cat /proc/version 2.Linux version 2.4.20-8 (bhcompile@porky.devel.redhat.com) (gcc version 3.2.2 20030222 (Red Hat Linux 3.2.2-5)) #1 Thu Mar 13 17:54:28 EST 2003
End