我知道我可以通過引用複製函數,但我想了解下面的代碼中會產生段錯誤。Memcpy與函數指針導致段錯誤
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int return0()
{
return 0;
}
int main()
{
int (*r0c)(void) = malloc(100);
memcpy(r0c, return0, 100);
printf("Address of r0c is: %x\n", r0c);
printf("copied is: %d\n", (*r0c)());
return 0;
}
這是我的心理模型,我認爲應該工作。
進程擁有分配給r0c的內存。我們正在複製對應於return0的數據段的數據,並且複製成功。
我認爲解引用函數指針與調用函數指針指向的數據段相同。如果是這種情況,那麼指令指針應該移動到對應於r0c的數據段中,該段將包含函數return0的指令。對應於return0的二進制代碼不包含任何將取決於return0地址的跳轉或函數調用,因此它應該只返回0並恢復ip ... 100個字節對於函數指針來說肯定是足夠的,而且0xc3很好在r0c的範圍內(在字節11處)。
那麼爲什麼分段錯誤?這是對C函數指針語義的誤解嗎?還是有一些安全特性阻止了我不知道的自修改代碼?
'的printf( 「R0C的地址是:%X \ n」 個,R0C);'沒有很好地限定。 – chux
有些東西告訴我,整個事情沒有很好的定義。 – HolyBlackCat
首先,函數(代碼)駐留在標記爲可執行文件的內存段中。分配的數據不那麼明顯,特別是如果您的系統正在使用DEP(數據執行預防)。如果您希望執行數據段中的代碼,則需要弄清楚如何將數據標記爲可執行文件。其次,'memcpy(r0c,return0,100);'可能是從內存末尾複製而來的。第三,包含代碼的內存地址很可能不受訪問。 – GreatAndPowerfulOz