我目前正在学习C编程,并且由于我是Python程序员,因此我不确定C。我只是偶然发现了一件非常奇怪的事情。<<<<<<<<<</p>
void test_realloc(){
// So this is the original place allocated for my string
char * curr_token = malloc(2*sizeof(char));
// This is really weird because I only allocated 2x char size in bytes
strcpy(curr_token, "Davi");
curr_token[4] = 'd';
// I guess is somehow overwrote data outside the allocated memory?
// I was hoping this would result in an exception ( I guess not? )
printf("Current token > %sn", curr_token);
// Looks like it's still printable, wtf???
char *new_token = realloc(curr_token, 6);
curr_token = new_token;
printf("Current token > %sn", curr_token);
}
int main(){
test_realloc();
return 0;
}
因此,问题是:我怎么能比其分配的大小将更多的字符写入字符串?我知道我应该自己处理杂乱的内存,但这是否意味着当我在指定的内存外写入时,没有任何迹象?
我想完成的工作
- 分配一个4个字符( null char(字符串,我将写4个名字的char
- 重新分配内存以递增我的名字的最后一个字符
知道我应该自己处理杂货的内存,但这是否意味着当我在指定的内存外写入时,没有迹象?
欢迎参加C编程:)。总的来说,这是正确的:您可以做错事,不会收到这种情况。实际上,在某些情况下,您可以做错事,并且永远不会在运行时看到问题。但是,在其他情况下,您会看到崩溃或其他对您没有意义的行为。
关键项是不确定的行为。如果您继续在C中进行编程,则应该熟悉这一概念。这意味着听起来像:如果您的程序违反了某些规则,则该行为是 dem> dem> dem> - 它可能会做您想要的,它可能崩溃,可能会做一些不同的事情。更糟糕的是,它可能会做您想要的时间最多的,但偶尔会做不同的事情。
正是这种机制允许C程序快速 - 因为它们在运行时没有做很多您可以从Python中使用的检查 - 但这也使C危险。编写不正确的代码并且不了解它很容易;然后,稍后在其他地方进行微妙的更改,或使用其他编译器或操作系统,并且代码将不再按照您想要运行。在某些情况下,这可能会导致安全漏洞,因为不必要的行为可能是可利用的。
假设您的数组如下所示。
int arr[5] = {6,7,8,9,10};
从数组的基础知识中,数组的名称是指向数组基本元素的指针。在这里,arr是数组的名称,是指向基本元素的指针,为6。因此, *arr
,字面上是, *(arr+0)
给了您6个输出, *(arr 1(给了您7等。在。在这里,数组的大小为5个整数元素。现在,尝试访问第10元素,尽管数组的大小为5个整数。arr[10]
。这不会给您带来错误,而是会给您一些垃圾价值。由于ARR只是一个指针,因此取消率作为arr+0
,arr+1
,arr+2
等。以相同的方式,您也可以使用基本数组指针访问arr+10
。现在,尝试使用此示例理解您的上下文。尽管您仅针对角色分配了2个字节的内存,但您可以使用指针分配的两个字节以外的内存。因此,这不会给您带来错误。另一方面,您可以预测机器上的输出。但是,不能保证您可以预测另一台计算机上的输出(可能是您在计算机上分配的内存中充满了零,并且可能是第一次使用这些特定的内存位置!(。在声明中, char *new_token = realloc(curr_token, 6);
请注意,您正在重新关注curr_token
指向new_token
指针指向的6个字节数据的内存。现在,new_token
的初始大小为6个字节。
通常会实现 malloc
,以使其分配到等于16个字节的段落(基本对齐(的内存块(基本对齐(。
因此,当您要求分配例如2个字节Malloc时,实际上分配了16个字节。这允许在调用realloc
时使用相同的内存。
根据C标准(7.22.3内存管理功能(
- ...如果分配成功是适当对齐的,则返回的指针 可以将其分配给指向任何类型的对象的指针 具有基本对齐要求,然后用于访问此类 分配空间中的对象或一系列此类对象 (直到明确交易空间(。
尽管如此,您不应该依靠这种行为,因为它不是规范性的,因此被认为是不确定的行为。
未在C中执行自动界限检查。程序行为是不可预测的。如果您在为另一个过程保留的内存中写作,您将以细分故障结束,否则您只会损坏数据,ECC ...