#include <stdio.h> #include <stdbool.h> #include <stdlib.h> void fun(int* a, bool* visit, int x) { if (12 == x) { int temp = a[0] + a[2] + a[5] + a[7]; if (1 == a[0] && 8 == a[1] && 3 == a[11] && temp == a[0] + a[3] + a[6] + a[10] && temp == a[1] + a[2] + a[3] + a[4] && temp == a[1] + a[5] + a[8] + a[11] && temp == a[7] + a[8] + a[9] + a[10] && temp == a[11] + a[9] + a[6] + a[4]) printf("%d\n", a[5]); return; } for (int i = 1; i <= 12; i++) { if (visit[i]) continue; visit[i] = true; a[x] = i; fun(a, visit, x + 1); visit[i] = false; } } int main() { int* a = calloc(12, sizeof(int)); bool* visit = calloc(12, sizeof(bool)); fun(a, visit, 0); return 0; }
解决方案
10
有越界访问 0~12应该分配13个单元
5
越界后的行为是未定义的,你这次正常运行,可能下次就会挂。和编译器无关
5
代码手打实测
int* a =(int *) calloc(12, sizeof(int));
bool* visit = (bool*)calloc(12, sizeof(bool));
这里需要类型转换
#include <stdbool.h> 头文件未知 windows库文件种没有
主函数增加getchar() 函数,使控制台窗口停留
并没有输出结果,本人也很诧异
真心不理解,你那一坨&&条件是什么,反正没有输出任何数据
int* a =(int *) calloc(12, sizeof(int));
bool* visit = (bool*)calloc(12, sizeof(bool));
这里需要类型转换
#include <stdbool.h> 头文件未知 windows库文件种没有
主函数增加getchar() 函数,使控制台窗口停留
并没有输出结果,本人也很诧异
真心不理解,你那一坨&&条件是什么,反正没有输出任何数据
5
按照13 分配内存,计算出结果是10
10
你分配的大小是12个元素,下标有效范围是0~11,for (int i = 1; i <= 12; i++) 当i为12时已经越界,未定义行为
10
其实电脑开机后物理内存的每个字节都是可读写的,从来不会原因是所谓的new、delete或malloc、free而被创建、销毁。区别仅在于操作系统内存管理模块在你读写时能否能发现并能否采取相应动作而已。操作系统管理内存的粒度不是字节而是页,一页通常为4KB。
判断能否越界访问,可以在数组的最后一个元素之后对应的地址处设置数据读写断点。假如该地址对应其它变量干扰判断,可将数组多声明一个元素,并设置数据读写断点在该多出元素对应的地址上。
判断能否越界访问,可以在数组的最后一个元素之后对应的地址处设置数据读写断点。假如该地址对应其它变量干扰判断,可将数组多声明一个元素,并设置数据读写断点在该多出元素对应的地址上。
#include <time.h> #include <stdlib.h> #include <windows.h> int main() { int a,b[11];//本来是b[10],为判断哪句越界,故意声明为b[11] srand((unsigned int)time(NULL));//按两次F11,等黄色右箭头指向本行时,调试、新建断点、新建数据断点,地址:&b[10],字节计数:4,确定。 while (1) {//按F5,会停在下面某句,此时a的值为10,b[10]已经被修改为对应0..4之一。 b[(a=rand()%11)]=0; Sleep(100); b[(a=rand()%11)]=1; Sleep(100); b[(a=rand()%11)]=2; Sleep(100); b[(a=rand()%11)]=3; Sleep(100); b[(a=rand()%11)]=4; Sleep(100); } return 0; }