1. 程式人生 > >指標值為空作為函式引數傳入

指標值為空作為函式引數傳入

下面以一個例子來引出這種錯誤

#include <iostream>
using namespace std;
#include <stdlib.h>
#include <string.h>
void func(int *p)
{
    p = (int *)malloc(sizeof(int) * 10);
    memset(p, 0, sizeof(p));
    p[0] = 1;
}
int main()
{
    int *p = NULL;
    func(p);
    cout << p[0] << endl;
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

一個很簡單的函式,就是給*p在函式中分配空間並將p[0]置成1,最後列印輸出p[0]。但是執行的結果卻是segmengt fault

我們通過檢視這段程式的彙編程式碼來分析一下出現段錯誤的原因。

Dump of assembler code for function func(int*):
   0x00000000004008cd <+0>:     push   %rbp
   0x00000000004008ce <+1>:     mov    %rsp,%rbp
   0x00000000004008d1 <+4>:     sub    $0x20,%rsp
   0x00000000004008d5 <+8>:     mov    %rdi,-0x18(%rbp)
   0x00000000004008d9 <+12>:    mov    $0x28,%eax
   0x00000000004008de <+17>:    mov    %rax,%rdi
   0x00000000004008e1 <+20>:    callq  0x400780 <
[email protected]
> 0x00000000004008e6 <+25>: mov %rax,-0x8(%rbp) 0x00000000004008ea <+29>: mov -0x8(%rbp),%rax 0x00000000004008ee <+33>: mov $0x8,%edx 0x00000000004008f3 <+38>: mov $0x0,%esi 0x00000000004008f8 <+43>: mov %rax,%rdi 0x00000000004008fb <+46>: callq 0x400750 <[email protected]
> 0x0000000000400900 <+51>: mov -0x8(%rbp),%rax 0x0000000000400904 <+55>: movl $0x1,(%rax) 0x000000000040090a <+61>: leaveq 0x000000000040090b <+62>: retq End of assembler dump.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

重點放在

    sub $0x20,%rbp
    mov %rdi,-0x18(%rbp)
  • 1
  • 2
  • 3

這兩句彙編程式碼上。

sub $0x20,%rbp的意思是給棧分配0x20大小的空間。

mov %rdi,-0x18(%rbp)的意思是把函式的第一個引數的值壓入棧中儲存。 
這說明了什麼?說明了函式中的*p其實是一個臨時變數,和主函式並不是同一個*p了。給臨時變數申請記憶體並賦值當前不能反映到主函式的*p上,所以主函式的*p還是個空指標,而列印空指標當然就段錯誤了。

下面介紹兩種解決方法: 
1.函式返回臨時指標的地址

#include <iostream>
using namespace std;
#include <stdlib.h>
#include <string.h>
int* func(int *p)
{
    //此時的p是個臨時指標
    p = (int *)malloc(sizeof(int) * 10);
    memset(p, 0, sizeof(p));
    p[0] = 1;
    return p;  //返回地址
}
int main()
{
    int *p = NULL;
    p = func(p);
    cout << p[0] << endl;
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

2.傳入指向指標的指標

#include <iostream>
using namespace std;
#include <stdlib.h>
#include <string.h>
//*p儲存的是main函式*ptr的地址
void func(int **p)
{
    *p = (int *)malloc(sizeof(int) * 10);
    memset(*p, 0, sizeof(*p));
    *p[0] = 1;
}
int main()
{
    int *ptr = NULL;
    func(&ptr);
    cout << ptr[0] << endl;
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

相關推薦

標值作為函式引數傳入

下面以一個例子來引出這種錯誤:#include <iostream> using namespace std; #include <stdlib.h> #include <string.h> void func(int *p) { p = (int *)malloc

把tuple或者list裡的元素作為函式引數傳入

1、tuple或list中的所有元素傳入一個函式的引數列表中: 需求函式如下: tuple = (1, "foo", "bar") def myfun(number, str1, str2): return (number * 2, str1 + str2, str2 + st

java 11:陣列作為函式引數,陣列做函式返回值

1 陣列作為引數 我們可以將陣列作為引數,傳入到函式中,其實就像我們main函式中 public void main(String [] args){};就是用陣列作為函式引數; 又如, publicclass ArrayPar  {  publicstaticvoid

指標和引用 作為函式引數

*和& * * 有兩個作用,一個是作為識別符號來表示這是一個指標(宣告變數時的等號左邊),也就是說存放的是地址,另外一個是作為運算子來取值(賦值等號左邊)。 int *p=NULL; int a = 1; p = &a; cout<<p<<

二維陣列作為函式引數

https://www.cnblogs.com/alantu2018/p/8465894.html   1、二維陣列的概念   在C語言中,二維陣列實際上是一種特殊的一維陣列,它的每個元素也是一個一維陣列。因此,二維陣列下標形式正確寫法如下:int arrays[i][j]。陣

C++ 之std::function() 作為函式引數入口 詳解

1. 關於std::function() 在C語言的時代,我們可以使用函式指標來吧一個函式作為引數傳遞,這樣我們就可以實現回撥函式的機制。到了C++11以後在標準庫裡引入了std::function模板類,這個模板概括了函式指標的概念 函式指標只能指向一個函式,而std::function物件可

普通值、指標、引用作為函式引數時的理解

       很多時候,我們都會看到在教科書上寫著各種值傳遞,引用傳遞,一看一大堆,有時候看的還容易迷糊,什麼情況該怎麼傳總是區分不清,下邊我們用一小版塊並結合程式碼例項講解下。 一、值傳遞 // 普通值傳遞 void test(int num) {

C語言指標作為函式引數傳遞學習(一)

1. 一維指標做函式引數 傳入的指標為NULL 比如下面的例子,很多人都會理解錯: #include <stdio.h> void test(char *string) { string = "hello world"; } int main() { cha

結構體陣列作為函式引數

把結構體陣列名作為函式的一個引數,然後在這個函式的函式裡面繼續作為引數,把一個值賦給這個結構體陣列的一個變數,我再賦值的地方是有值的,在函式裡面也是有值的,但是出了這個函式回到主函式時,這個結構體陣列的變數的值就為空了。為什麼呢?因為我在使用這個函式是這樣的, iRetur

指標作為函式引數 進行記憶體釋放 並置NULL

author:張繼飛 寫在前面,前面寫了程式碼封裝free函式,但是呼叫封裝並退出後,指標並不為NULL,導致接下來以此作為判斷條件的時候就出現問題了。先前封裝函式為void _free_p_(void *ptr),通過分析,指標作為函式引數傳遞時只是傳遞了指標所指向的地址,將其賦給一個

有關 陣列作為函式引數 & 區域性變數和全域性變數及其應用

一、陣列blabla 1.0陣列元素作函式實參。 (1).陣列元素可以用作函式實參,但不能是形參。(給陣列分配的儲存單元是連續的) 2.0一維陣列名作函式引數。 (1)陣列元素作實參時,向形參變數傳遞的時陣列元素的值。 陣列名作實參時,向形參傳遞的時陣列首元素的地址。

C++(筆記)容器(vector)作為函式引數如何傳參

一、大致以下型別 void 函式名( vector< int> obj ); void 函式名( vector< int>* pobj ); void

c++中類物件直接作為函式引數所引起的問題。

這兩天在寫一個視訊轉換的程式,將H263/264編碼的視訊封裝成mov格式,用c++實現。 Wiki上說Apple的mov格式是典型的over engineering,設計的非常複雜,各種資訊使用atom原子封裝,一個atom裡面遞迴地巢狀著另外一個atom,atom的種類

函式指標作為函式引數函式作為函式引數

轉載於:http://blog.csdn.net/vlily/article/details/7244682 轉載於:http://blog.csdn.net/shengnan_wu/article/details/8116935 轉載於:http://blog.csdn.net/callm

C語言經典例題--結構體指標變數作為函式引數的傳遞

#include <stdio.h> #include <string.h> struct student { int age; char sex; char name[30]; }; void inputstudent(struct stu

C++多維陣列:儲存方式、訪問方式和作為函式引數

C++中陣列可以巢狀,就是多維陣列。 多維陣列儲存與訪問方式 二維陣列:一維陣列可對應數學中的向量,而二維陣列可對應矩陣,可用一個二維陣列儲存矩陣。 圖1  二維陣列mat示意圖 二維陣列的橫向稱為行,縱向稱為列,上面這個陣列為三行六列。定義二維陣列的通用格式為:    

c++之指標作為函式引數傳遞的問題

轉自:http://blog.csdn.net/fjb2080/article/details/5623427   原創文章,轉載請註明出處,謝謝! 作者:清林,部落格名:飛空靜渡   部落格地址:http://blog.csdn.net/fjb2080 &n

指標作為函式引數傳遞 (轉載)

這幾天在學習C過程中,在使用指標作為函式引數傳遞的時候出現了問題,根本不知道從何得解:原始碼如下:    createNode(BinNode *tree,char *p)    {        tree = (BinNode *) malloc(sizeof(BinNo

C++用指向函式的指標作為函式引數

示例: #include <iostream> using namespace std; int add(int x, int y){ return x + y; } int sub(int x, int y){ return x - y; } int opera

C++引用作為函式引數

一. 值傳遞1. 利用值傳遞方式,實際上是把實參的內容複製到形參中,實參和形參是存放在兩個不同的記憶體空間中。在函式體內對形參的一切修改對實參都沒有影響2. 如果形參是類的物件,利用值傳遞的話每次都要呼叫類的建構函式構造物件,效率比較低二. 指標傳遞(地址傳遞)1. 當進行指標傳遞的時候,形參是指標變數,實參