第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問題,去搜搜看,總會(huì)有你想問的

通過 cgo 調(diào)用fts_open時(shí)出現(xiàn)分段沖突錯(cuò)誤

通過 cgo 調(diào)用fts_open時(shí)出現(xiàn)分段沖突錯(cuò)誤

Go
SMILET 2022-09-19 20:54:56
我正在測(cè)試cgo,每個(gè)簡(jiǎn)單的你好世界,如代碼,工作得很好。但我對(duì)下面的C代碼有問題。C 代碼是遍歷目錄樹并對(duì)文件大小求和的代碼。如果我用go命令構(gòu)建,那么構(gòu)建是可以的,沒有錯(cuò)誤。但是在運(yùn)行時(shí),發(fā)生了“分段沖突”錯(cuò)誤bash$./walkdir fatal error: unexpected signal during runtime execution[signal SIGSEGV: segmentation violation code=0x1 addr=0x1 pc=0x7f631e077c1a]. . . .-------------------------------------------------------------package main/*#include <stdint.h>#include <fts.h>#include <sys/stat.h>uintmax_t get_total_size(char *path){    uintmax_t total_size = 0;    FTS *fts = fts_open(&path, FTS_PHYSICAL, NULL);    FTSENT *fent;    while ((fent = fts_read(fts)) != NULL)        if (fent->fts_info == FTS_F)            total_size += fent->fts_statp->st_size;    fts_close(fts);    return total_size;}*/import "C"import "fmt"func main() {    fmt.Println(C.get_total_size(C.CString("/usr")))}
查看完整描述

2 回答

?
侃侃無極

TA貢獻(xiàn)2051條經(jīng)驗(yàn) 獲得超10個(gè)贊

fts_open 定義如下:

fts_open()
該函數(shù)獲取指向一個(gè)字符指針數(shù)組的指針,這些指針命名一個(gè)或多個(gè)路徑,這些路徑構(gòu)成了要遍歷的邏輯文件層次結(jié)構(gòu)。數(shù)組必須由指針終止。fts_open()null

C沒有對(duì)數(shù)組的直接支持;它只有指針。在你的情況下,你傳遞一個(gè)有效的指針,但它不在一個(gè)數(shù)組中,該數(shù)組有一個(gè)指針作為緊隨其后的元素,所以繼續(xù)掃描過去的內(nèi)存 - 尋找一個(gè)指針, 并最終嘗試在某個(gè)地址讀取內(nèi)存,這是禁止這樣做的(通常是因?yàn)樵摰刂返捻撁鏇]有被分配)。fts_openNULLfts_open&pathNULL

修復(fù)它的一種方法是創(chuàng)建該數(shù)組并在C端初始化它。
看起來你正在使用一個(gè)相當(dāng)最新的C標(biāo)準(zhǔn),所以讓我們只使用直接文字來初始化數(shù)組:

package main


/*

#include <stddef.h> // for NULL

#include <stdint.h>

#include <stdlib.h> // for C.free

#include <fts.h>

#include <sys/stat.h>


uintmax_t get_total_size(char *path)

{

    uintmax_t total_size = 0;

    char * path_argv[2] = {path, NULL};

    FTS *fts = fts_open(path_argv, FTS_PHYSICAL, NULL);

    FTSENT *fent;

    while ((fent = fts_read(fts)) != NULL)

        if (fent->fts_info == FTS_F)

            total_size += fent->fts_statp->st_size;

    fts_close(fts);

    return total_size;

}

*/

import "C"


import (

    "fmt"

    "unsafe"

)


func main() {

    cpath := C.CString("/usr")

    defer C.free(unsafe.Pointer(cpath))

    fmt.Println(C.get_total_size(cpath))

}

請(qǐng)注意,您的程序有一個(gè)錯(cuò)誤和一個(gè)可能的問題:

  • 一個(gè)錯(cuò)誤是,調(diào)用通過從鏈接的 C 庫執(zhí)行調(diào)用來分配內(nèi)存塊,而您沒有釋放該內(nèi)存塊。C.CStringmalloc(3)

  • 該符號(hào)定義在“標(biāo)準(zhǔn)定義.h”中;編譯時(shí)可能會(huì)或可能不會(huì)收到錯(cuò)誤。NULL

我已經(jīng)在我的示例中修復(fù)了這兩個(gè)問題。

對(duì)我們的示例的進(jìn)一步改進(jìn)可能是利用函數(shù)在單次運(yùn)行中掃描多個(gè)路徑的能力;如果我們要實(shí)現(xiàn)它,那么為Go端的第一個(gè)參數(shù)分配數(shù)組會(huì)更有意義:fts_*fts_open

package main


/*

#include <stddef.h>

#include <stdint.h>

#include <stdlib.h>

#include <fts.h>

#include <sys/stat.h>


uintmax_t get_total_size(char * const *path_argv)

{

    uintmax_t total_size = 0;

    FTS *fts = fts_open(path_argv, FTS_PHYSICAL, NULL);

    FTSENT *fent;

    while ((fent = fts_read(fts)) != NULL)

        if (fent->fts_info == FTS_F)

            total_size += fent->fts_statp->st_size;

    fts_close(fts);

    return total_size;

}

*/

import "C"

import (

    "fmt"

    "unsafe"

)


func main() {

    fmt.Println(getTotalSize("/usr", "/etc"))

}


func getTotalSize(paths ...string) uint64 {

    argv := make([]*C.char, len(paths)+1)

    for i, path := range paths {

        argv[i] = C.CString(path)

        defer C.free(unsafe.Pointer(argv[i]))

    }


    return uint64(C.get_total_size(&argv[0]))

}

請(qǐng)注意,這里我們沒有顯式地將最后一個(gè)參數(shù)清零,因?yàn)榕cC相反,Go用零初始化每個(gè)分配的內(nèi)存塊,因此一旦分配,其所有內(nèi)存都已歸零。argvargv


查看完整回答
反對(duì) 回復(fù) 2022-09-19
?
楊魅力

TA貢獻(xiàn)1811條經(jīng)驗(yàn) 獲得超6個(gè)贊

您收到錯(cuò)誤,因?yàn)椤癴ts_open”需要一個(gè)指向數(shù)組的字符指針,該數(shù)組以 NULL 結(jié)尾,如 char *argv[] = { 路徑,NULL };.。(https://linux.die.net/man/3/fts_open)


package main


/*

#include <stdint.h>

#include <fts.h>

#include <sys/stat.h>


uintmax_t get_total_size(char *path)

{

    uintmax_t total_size = 0;

    char *argv[] = { path, NULL };

    FTS *fts = fts_open(argv, FTS_PHYSICAL, NULL);

    if (fts == NULL)

        return 0;

    FTSENT *fent;

    while ((fent = fts_read(fts)) != NULL)

        if (fent->fts_info == FTS_F)

            total_size += fent->fts_statp->st_size;

    fts_close(fts);

    return total_size;

}

*/

import "C"

import "fmt"


func main() {

    fmt.Println(C.get_total_size(C.CString("/usr")))

}

因此添加數(shù)組指針將修復(fù)代碼。


使用 GCC 編譯時(shí),相同的代碼也有效,但fts_open返回 NULL。我猜gcc和cgo之間的優(yōu)化有一些區(qū)別(不是很確定)


我嘗試了一些測(cè)試結(jié)果,并能夠發(fā)現(xiàn),當(dāng)使用GCC編譯時(shí),字符**指針被空終止,但在cgo的情況下,它沒有以空值終止,所以你得到“SIGSEGV”,因?yàn)槟愕拇a正在讀取無效的內(nèi)存引用。


#include <stdio.h>

#include <string.h>


void try(char **p)

{

   while (*p != NULL)

   {

      printf("%zu\n", strlen(*p));

      ++p;

   }

}


void get_total_size(char *path)

{

   try(&path);

}

int main()

{

   get_total_size("/usr");

}

c 代碼(有效)


package main

/*

#include <stdio.h>

#include <string.h>


void try(char **p)

{

   while (*p != NULL)

   {

      printf("%zu\n", strlen(*p));

      ++p;

   }

}


void get_total_size(char *path)

{

   try(&path);

}

*/

import "C"


func main() {

    C.get_total_size(C.CString("/usr"))

}

相同的去代碼,你會(huì)面臨錯(cuò)誤


查看完整回答
反對(duì) 回復(fù) 2022-09-19
  • 2 回答
  • 0 關(guān)注
  • 109 瀏覽

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)