鍍金池/ 問答/ C++問答
硬扛 回答

可能是因為你的目錄中有空格導(dǎo)致命令行參數(shù)出錯。建議把代碼放到別的目錄下。比如D:projectsprotobuf下面編譯。

焚音 回答

編譯成什么了?如果有C風(fēng)格的API的話,可以用ffi。

艷骨 回答

Update1

注意, 因爲(wèi)窩太垃圾了, 以下答案很有可能存在不嚴(yán)謹(jǐn), 甚至錯誤的部分, 窩也在不斷的修訂. 所以, 想踩的話請隨意, 但是窩不太想刪, 刪了話自己可能沒有動力總結(jié)了, 好吧, 窩的確很自私. 但是窩相信終有一天這個答案會self-contained並且邏輯不再混亂.

Update2

I don't have Chinese input method editor, so I will write in English(but too lazy to translate the original contexts into English, So previous Chinese wording preserved)

很不幸, 之所以你搜segmentfault都是這個論壇, 有兩個原因,

  1. 因爲(wèi)這個網(wǎng)站的域名就是segmentfault.com.
  2. 是因爲(wèi)你搜索的姿勢不對, 它不是一個單詞...而是一個詞組: segment fault. 當(dāng)然, 也有縮寫: segfault, 或者Segmentation-fault.

1.1. segment fault既不是linux特有的, 也不是c++特有的, 甚至從語言規(guī)範(fàn)中, 它不屬於c++, 因爲(wèi)c++的標(biāo)準(zhǔn)文檔中沒有對Segmentation fault沒有過定義. 喂雞百科中它被定義爲(wèi):

In computing, a segmentation fault (often shortened to segfault) or access violation is a fault, or failure condition, raised by hardware with memory protection, notifying an operating system (OS) the software has attempted to access a restricted area of memory (a memory access violation).

長話短說, 就是軟件訪問了不該訪問的memory, 而硬件具有內(nèi)存保護功能. 具體的說, 就是當(dāng)MMU檢測到非法內(nèi)存被訪問了, 那麼它就讓CPU產(chǎn)生一個exception.

1.2. c或者c++這種既接近底層, 又古老的語言會引起段錯誤.
1.3. 書沒什麼好推薦的, 畢竟這玩意一般第一天寫c/c++就會碰到...碰到多了自然知道了, 非要推薦的話去看些操作系統(tǒng)之類的書(CSAPP, OSTEP, etc)會有比較深刻的認(rèn)知吧,比如trap. 不過也別迷信讀書, 畢竟現(xiàn)在互聯(lián)網(wǎng)這麼發(fā)達(dá). 你把英文喂雞上的關(guān)於它的內(nèi)容看一邊也差不多了.

2.1. bus error, stack overflow(更新: 有一種說法是stack overflow本身不是錯誤(error/fault), 但是它的存在會觸發(fā)其它錯誤(error/fault), 其中之一就是Segmentation fault, 因爲(wèi)call stack溢出後, 程序有可能對非法地址進些讀寫操作. ......好多好多呢, 你去這個列表看下,
2.2. 至於Segmentationfault這倆詞語, 我們從操作系統(tǒng)講起:

假想下你的操作系統(tǒng)就是一個巨大的庫, 所有操作(包括應(yīng)用軟件)都只要調(diào)用這個庫(的API)就行了, 沒有任何權(quán)限限制, 這其實就是早期操作系統(tǒng)的設(shè)計形態(tài), 後來人們逐漸意識到這麼做是不安全的, 放到今天應(yīng)該會很容易明白, 比如你肯定不希望手機流氓軟件(應(yīng)用軟件)訪問你在磁盤上的個人信息吧, 但是我們依然要確保操作系統(tǒng)有權(quán)限訪問, 所以我們需要一場革命, 帶來一個新的內(nèi)存保護機制, 或者說是一個新的文件系統(tǒng), 當(dāng)然, 這個文件系統(tǒng)肯定不能作爲(wèi)一個庫, 不然還是什麼都沒有改變, 最終, 這個革命者名爲(wèi)system call, 其實現(xiàn)是通過硬件(CPU的trap)指令, 伴隨它的還有user mode, kernel mode(這兩個mode是針對CPU的, 比如, CPU可以用一個bit來表徵, 0代表kernel mode, 1代表kernel mode等. 具體的做法就是system call賦予操作系統(tǒng)更高的硬件優(yōu)先級. 應(yīng)用軟件處於user mode, 不能進行讀寫磁盤/物理內(nèi)存等操作, 它將某些數(shù)值放在寄存器或棧幀, 表示自己希望從操作系統(tǒng)處得到那些東西, 然後應(yīng)用軟件調(diào)用trap)指令, 即執(zhí)行system call, 此時CPU轉(zhuǎn)換爲(wèi)kernel mode, 並且跳轉(zhuǎn)到一些指令處, 這些指令是屬於操作系統(tǒng)的, 他們會聆聽(通過之前的寄存器或者棧幀)應(yīng)用軟件, 然後也切換到kernel mode, 執(zhí)行這些請求.

However, how can we separate user mode from kernel mode? Two approaches:

  1. Protection ring
  2. Have a single address space for all software, and rely on the programming language's virtual machine to make sure that arbitrary memory cannot be accessed – applications simply cannot acquire any references to the objects that they are not allowed to access

好, 爲(wèi)了鞏固記憶, 接下來我們換一種問法, 什麼情況下system call會被執(zhí)行呢?
答案還是trap)(需要注意的是此處的trap)不同於上面的trap)指令, 是兩回事, 這裏的trap)是一個泛指, 是interrupt的子集, 特指非硬件層面的interrupt). 經(jīng)常, trap)也可以用其同義詞--falut或者exception來代替. 有些地方會將這些分開, 比如如果你關(guān)注國外各個大學(xué)的操作系統(tǒng)(設(shè)計(與實現(xiàn))的課的話, 會發(fā)現(xiàn)他們往往會對其定義有差別, 比如由硬件還是軟件觸發(fā)之類, 具體如fault有時會特指page fault, 再比如Intel microprocessor manuals裏將synchronous interrupts定義爲(wèi)exceptions, asynchronous interrupts 定義爲(wèi)interrupts, 但是很多時候大家對其區(qū)分不是很嚴(yán)格, 經(jīng)常一個interrupt signal就包括前面?zhèn)z貨了, 不過這個實現(xiàn)都是平臺相關(guān)的, 可能別的體系就有另一套說辭, 或者能更一步細(xì)化, 比如在古老的Linux/i386中, 其實現(xiàn)就是interrupt 0x80

說完fault, 我們再回到Segmentation, 其實它就是一段內(nèi)存, 但是帶有一個值來標(biāo)記內(nèi)存, 並且還包含偏移量, 當(dāng)然也分爲(wèi)物理內(nèi)存和虛擬內(nèi)存, 這裏只說虛擬內(nèi)存, 因爲(wèi)你編寫的c/c++程序用到的都是虛擬內(nèi)存而不是物理內(nèi)存. Segmentation fault]合在一起就是一個trap/exception/fault/software interrupt, 因爲(wèi)它訪問了不該訪問的內(nèi)存.

尋仙 回答

1.X%y結(jié)果為X除以Y的余數(shù),余數(shù)<=除數(shù),而余數(shù)>k,那么y肯定>k
2.count += n/y(y-k) 等價于 count = count + n/y(y-k)
3.和2同理

你好胸 回答
#include <cstdio>
int add()
{
  int a=2;
  int b=3;
  int c=a+b;
  return c;
}

int main()
{
  int *p;
  int i = add();
  p=&i;
  *p=20;
  printf("%d", *p);
  fflush(stdout);
  return 0;
}

報錯信息很明顯了, c++不允許從int轉(zhuǎn)為int*.
好好份書或者教程看看吧...

墨染殤 回答

C#是半默認(rèn)break,你不寫會編譯器會發(fā)錯誤

哚蕾咪 回答

釋放部分沒錯。

free(row);
row = NULL;
free(col);
col = NULL;

這段代碼的問題是 malloc 之后沒有 memset。

祉小皓 回答

如果你使用 tcp 的話,對方一定是可以收到的;而如果使用的 udp(一般不用 udp 呢,除非有啥特殊需求),又要保證可靠,那就要在應(yīng)用層實現(xiàn)可靠,可以參考kcp。

尛曖昧 回答

\n代表換行符,意思是輸入遇到換行符就結(jié)束

命于你 回答

forEach會把你的函數(shù)多封裝一層,自然無法return

const findSelectedLabel = (items, name) => {
  for (let i = 0; i != items.length; ++i) {
    const item = items[i]
    if (item.name === name) {
      return item.label
    } else if (item.items && Array.isArray(item.items)) {
      const label = findSelectedLabel(item.items, name)
      if (label) {
        return label
      }
    }
  }
}

const label = findSelectedLabel(navItems, navName)
console.log(`find ${navName} -> ${label}`)
拼未來 回答

不就是搭建自己的NPM倉庫,網(wǎng)上有很多教程的,或者把自己的組件直接上傳到官方的NPM倉庫

笨尐豬 回答

你要知道TCP是流式協(xié)議,沒有消息邊界的,UDP是有消息邊界的,所以你發(fā)送端的數(shù)據(jù),到接收端這邊,可能需要一次,或者兩次,或者一次把兩次發(fā)送的數(shù)據(jù)都接收了
610439-20160528150523303-1600111497.png
你可以想象你是在接收水流,所以你是不知道它那里結(jié)束的
可以搜索TCP粘包問題,一般解決方案有:

  • 發(fā)送定長包。如果每個消息的大小都是一樣的,那么在接收對等方只要累計接收數(shù)據(jù),直到數(shù)據(jù)等于一個定長的數(shù)值就將它作為一個消息。
  • 包尾加上rn標(biāo)記。FTP協(xié)議正是這么做的。但問題在于如果數(shù)據(jù)正文中也含有rn,則會誤判為消息的邊界。
  • 包頭加上包體長度。包頭是定長的4個字節(jié),說明了包體的長度。接收對等方先接收包體長度,依據(jù)包體長度來接收包體。
  • 使用更加復(fù)雜的應(yīng)用層協(xié)議。
逗婦惱 回答

example 3 是擴展性比較好的寫法。說擴展性好是指在增加新的 Data 類型時不要改動任何代碼。第二種模板的方式要求 Data 類型必須具有一致的結(jié)構(gòu)才可以,太脆弱了。
example 3 的問題是對使用者不友好,每次調(diào)用都要寫 lambda, 如果有大量的調(diào)用就顯得代價過高了。可以通過提取輔助函數(shù)的方式解決(或者寫成 User 類的構(gòu)造函數(shù)),每增加一個 Data 類型就對應(yīng)增加這樣一個輔助函數(shù)(或者構(gòu)造函數(shù))
當(dāng)然,以上只適合示例代碼中這種簡單邏輯。實際項目中可能復(fù)雜的多,比如要訪問十幾種 Data 類型中的十幾個成員,這時候就有必要加一個抽象層了,所有的 User 類從一個公共的接口繼承下來,每種或者每幾種 Data 類型對應(yīng)一種實現(xiàn)?;蛘甙殉橄蠼涌诜旁趦?nèi)部,User 類作為對該抽象接口調(diào)用的一個包裝類,這種方式的好處是抽象層在內(nèi)部可以隨時修改。
具體怎么做只能具體問題具體分析了。

情未了 回答
  1. sys_siglist使用extern修飾,說明它是一個外部變量,聲明在其他頭文件中。

  2. 第一個const修飾的是數(shù)組變量中的元素, 即數(shù)組變量sys_siglist中的元素類型為const char *

  3. 第二個const修飾的是sys_siglist這個數(shù)組變量,即sys_siglist這個變量是const的,不能被修改,是只讀的。

淚染裳 回答

data中聲明變量不是應(yīng)該在return中嗎?
獲取后臺數(shù)據(jù)應(yīng)該在mounted 調(diào)用 ,
個人感覺,這個代碼結(jié)構(gòu)有點混亂

methods:{
    addPage(){
    this.page++;
    this.xxx()
    }
} 

page ++后,再次調(diào)用那個依賴page參數(shù)的方法

懶洋洋 回答

“尾遞歸”可以了解下,有遞歸的優(yōu)點,同時不用擔(dān)心棧溢出。

過客 回答

先獲取到終端上的多余字符,然后再等待用戶輸入。