2011-08-08 49 views
6

我應該使用什麼,當我想複製src_strdst_arr爲什麼?strincpy或strlcpy在我的情況下

char dst_arr[10]; 
char *src_str = "hello"; 

PS:我的頭正在讀的東西很多關於如何strncpystrlcpy後紡比我的計算機的磁盤速度更快。

注意:我知道strlcpy不是隨處可用。這不是關心的問題。

回答

20

strncpy從未正確的答案時,你的目標字符串零終止。 strncpy是一個函數,旨在與非終止的固定寬度字符串一起使用。更確切地說,它的目的是將零終止的字符串轉換爲非終止的固定寬度的字符串(通過複製)。換句話說,strncpy在這裏沒有意義。

您在這裏的真正選擇是在strlcpy和普通strcpy之間。

當您想要執行「安全」(即可能截短)複製到dst_arr時,要使用的正確功能是strlcpy

dst_ptr ...沒有「複製到dst_ptr」這樣的東西。您可以複製到dst_ptr指向的內存,但首先您必須確保它指向某處並分配該內存。有很多不同的方法來做到這一點。

例如,您可以使dst_ptr指向dst_arr,在這種情況下,答案與前一個案例中的相同 - strlcpy

或者您可以使用malloc分配內存。如果分配的內存量足夠保證字符串(即至少分配了strlen(src_str) + 1字節),則可以使用普通的strcpy甚至memcpy複製字符串。在這種情況下,沒有必要也沒有理由使用strlcpy,雖然有些人可能更喜歡使用它,因爲它以某種方式給予他們額外安全的感覺。

如果您有意分配較少的內存(即您希望您的字符串被截斷),那麼strlcpy將成爲使用的正確函數。

+1

謝謝。當你說「當你使用零終止的字符串工作時,strncpy從來不是正確的答案」,你的意思是源字符串或dest? – hari

+2

@hari:目標字符串。 'strncpy'是*轉換*函數,它將零終止的源字符串轉換爲非終止的固定寬度目標字符串。 – AnT

+0

所以,如果我的目標字符串是'char dst_arr [10];'這不是空終止的。那我應該用'strlcpy'正確嗎? – hari

4

strlcpy()比strncpy()更安全,所以你不妨使用它。
沒有它的系統通常會有一個s_strncpy()來做同樣的事情。

注意你不能複製任何東西到dst_ptr直到它指向的東西

+1

它有點安全,但也不安全。例如。 strlcpy截斷源字符串以適應目標,這是一種安全風險。 – rurban

2

我不知道strlcpy。我剛剛發現here說:

的strlcpy和strlcat函數複製並分別連接字符串 。它們被設計爲更安全,更一致,並且對於strncpy(3)和strncat(3)來說,更少的容易出錯的替換。

因此stripepy接縫更安全。

編輯:有完整的討論可用here

EDIT2

我意識到,我寫上面不回答你的問題的「你的情況」部分。如果你明白 strncpy的侷限性,我猜你可以使用它並在其周圍編寫好的代碼以避免其陷阱;但是如果你不確定你對限制的理解,請使用strlcpy。

我對strncpy和strlcpy的侷限性的理解是,你可以用strncpy(緩衝區溢出)做一些非常糟糕的事情,而用strlcpy可以做的最糟糕的事情是在這個過程中釋放一個字符。

+0

感謝您的解釋。如何在'strlcpy'中放一個字符?你能解釋一下嗎? – hari

+0

如果使用strncpy複製大於緩衝區的字符串,它將不會在緩衝區的末尾放置「\ 0」。如果你使用strlcpy,那麼''\ 0''會在那裏,但是你的緩衝區中會少一個字符。因此,如果有人在使用memcpy時使用了strncpy,那麼使用strlcpy而不是strncpy會使他失去焦點。 – jfg956

+0

謝謝。因此,當只使用'strlcpy'時,需要注意的是,您應該爲(src_length + 1爲null)提供目的地。正確? – hari

-1

首先,你的dst_ptr沒有分配空間,你沒有設置它指向其他空間,所以指定任何東西都可能導致分段錯誤。

strncpy()函數應該完全正常工作 - 只是做:

strncpy(dst_arr, src_str, sizeof(dst_arr)); 

,你知道你不會溢出dst_arr。如果使用更大的src_str,則可能必須將自己的空終止符放在dst_arr的末尾,但在這種情況下,您的源是<您的dest,因此無論如何都會填充空值。

這在任何地方都行得通,而且它的安全,所以我不會看別的東西,除非它的智力好奇。

另外請注意,這將是很好用的10非幻數,讓你知道的是,大小strncpy()函數:)

+0

'strncpy'幾乎從不是正確的事情,因爲它零填充但不零終止。 OP希望'strlcpy',它的零終止和不填零。另外,在「這種情況下」討論是錯誤的,因爲當然只是一個例證的問題......真正的代碼不會將像「hello」這樣的固定字符串複製到一個固定大小的緩衝區, 。 –

-1

你不應該使用strncpy()函數,而不是是strlcpy本的尺寸相匹配。更好的使用

*dst_arr=0; strncat(dst_arr,src_arr,(sizeof dst_arr)-1); 

或沒有初始化

sprintf(dst_arr,"%.*s",(sizeof dst_arr)-1,src_arr); 

dst_arr這裏必須是一個數組不是指針。

+2

'strlcpy'可以用於OP的需要。 –

1

您應該始終使用標準功能,在本例中爲C11 strcpy_s()功能。不是strncpy(),因爲這是不安全的,不保證零終止。而不是僅限於OpenBSD的strlcpy(),因爲它也是不安全的,而OpenBSD總是提出它自己的發明,而這些發明通常不會成爲任何標準。

參見 http://en.cppreference.com/w/c/string/byte/strcpy

功能strcpy_s類似於BSD功能是strlcpy,不同之處在於 是strlcpy截斷源字符串以適應目的地(這是一個安全風險)

  • 是strlcpy確實不執行strcpy_s所做的所有運行時檢查
  • 通過將目標設置爲空字符串或在調用失敗時調用處理程序,strlcpy不會使失敗變得明顯。
  • 雖然strcpy_s由於潛在的安全風險而禁止截斷,但可以使用bounds-checked strncpy_s來截斷字符串。

如果您的C庫沒有strcpy_s,請使用safec庫。 https://rurban.github.io/safeclib/doc/safec-3.1/df/d8e/strcpy__s_8c.html