当有可能重新分配内存(更改指针)时,使用 "restrict" 是否有效?
Is it valid to use "restrict" when there is the potential for reallocating memory (changing the pointer)?
我正在尝试对代码进行一些优化,但我很难确定“限制”在这种情况下是否有用,或者它是否会导致问题。
我有一个传递两个字符串 (char*) 和一个 int (int*) 的函数。
第二个字符串在第一个字符串之后复制到内存中,位于由 int 指示的位置。如果这会超出为第一个字符串分配的内存,那么它必须在这样做之前为第一个字符串重新分配内存。使用新分配创建一个新指针,然后将原来的第一个字符串指针设置为等于它。
char* concatFunc (char* restrict first_string, char* const restrict second_string, int* const restrict offset) {
size_t block = 200000;
size_t len = strlen(second_string);
char* result = first_string;
if(*offset+len+1>block){
result = realloc(result,2*block);
}
memcpy(result+*offset,second_string,len+1);
*offset+=len;
return result;
}
上述函数被同样使用 restrict 关键字的其他函数重复调用。
char* addStatement(char* restrict string_being_built, ..., int* const restrict offset){
char new_statement[30] = "example additional text";
string_being_built = concatFunc(string_being_built,&new_statement,offset);
}
所以在 concatFunc 中 first_string 是受限制的(意味着指向的内存不会从其他任何地方更改)。但是如果我重新分配一个指针,它是它的一个副本,这会导致未定义的行为还是编译器足够聪明以适应这种情况?
基本上:限制指针参数但随后更改指针时会发生什么。
What happens when you restrict a pointer parameter, but then change the pointer.
这取决于指针的更改方式 - 在这种情况下,memcpy()
存在 UB 风险。
和char* result = first_string;
一样,继承了char* restrict first_string
的restrict
。
在result = realloc(result,2*block);
之后,result
和以前一样,通过result
访问不会与通过second_string
或offset
访问冲突 or result
是新内存,通过 result
访问不会与通过 second_string
或 offset
.
访问发生冲突
然而编译器能否知道新分配的result
具有realloc()
的上述两个属性之一?毕竟,realloc()
可能是 用户 定义的函数,编译器不应假设 result
现在有 restrict
属性。
因此memcpy()
危在旦夕
is the compiler smart enough to accommodate that?
我看不到它可以,除了警告 memcpy()
用法。
OP当然可以用memmove()
代替memcpy()
来避免这个问题。
在我看来,一个简化的例子是:
char* concatFunc (char* restrict first_string, char* restrict second_string) {
int block = rand();
first_string = foo(first_string, block);
// first_string at this point may equal second_string,
// breaking the memcpy() contract
memcpy(first_string, second_string, block);
return first_string;
}
或者更简单
char* concatFunc (char* /* no restrict */ first_string, char* restrict second_string) {
return memcpy(first_string, second_string, 2);
}
我正在尝试对代码进行一些优化,但我很难确定“限制”在这种情况下是否有用,或者它是否会导致问题。
我有一个传递两个字符串 (char*) 和一个 int (int*) 的函数。
第二个字符串在第一个字符串之后复制到内存中,位于由 int 指示的位置。如果这会超出为第一个字符串分配的内存,那么它必须在这样做之前为第一个字符串重新分配内存。使用新分配创建一个新指针,然后将原来的第一个字符串指针设置为等于它。
char* concatFunc (char* restrict first_string, char* const restrict second_string, int* const restrict offset) {
size_t block = 200000;
size_t len = strlen(second_string);
char* result = first_string;
if(*offset+len+1>block){
result = realloc(result,2*block);
}
memcpy(result+*offset,second_string,len+1);
*offset+=len;
return result;
}
上述函数被同样使用 restrict 关键字的其他函数重复调用。
char* addStatement(char* restrict string_being_built, ..., int* const restrict offset){
char new_statement[30] = "example additional text";
string_being_built = concatFunc(string_being_built,&new_statement,offset);
}
所以在 concatFunc 中 first_string 是受限制的(意味着指向的内存不会从其他任何地方更改)。但是如果我重新分配一个指针,它是它的一个副本,这会导致未定义的行为还是编译器足够聪明以适应这种情况?
基本上:限制指针参数但随后更改指针时会发生什么。
What happens when you restrict a pointer parameter, but then change the pointer.
这取决于指针的更改方式 - 在这种情况下,memcpy()
存在 UB 风险。
和char* result = first_string;
一样,继承了char* restrict first_string
的restrict
。
在result = realloc(result,2*block);
之后,result
和以前一样,通过result
访问不会与通过second_string
或offset
访问冲突 or result
是新内存,通过 result
访问不会与通过 second_string
或 offset
.
然而编译器能否知道新分配的result
具有realloc()
的上述两个属性之一?毕竟,realloc()
可能是 用户 定义的函数,编译器不应假设 result
现在有 restrict
属性。
因此memcpy()
危在旦夕
is the compiler smart enough to accommodate that?
我看不到它可以,除了警告 memcpy()
用法。
OP当然可以用memmove()
代替memcpy()
来避免这个问题。
在我看来,一个简化的例子是:
char* concatFunc (char* restrict first_string, char* restrict second_string) {
int block = rand();
first_string = foo(first_string, block);
// first_string at this point may equal second_string,
// breaking the memcpy() contract
memcpy(first_string, second_string, block);
return first_string;
}
或者更简单
char* concatFunc (char* /* no restrict */ first_string, char* restrict second_string) {
return memcpy(first_string, second_string, 2);
}