2009-06-04 20 views
6

wskazówka jest w tytule, ale w zasadzie odziedziczyłem kod, który ma ponad 800 instancji strcpy. Chcę napisać nową funkcję, a następnie zamienić strcpy na strcpy_mine.strcpy ... chcesz zastąpić ciągiem strcpy_mine, który będzie strncpy i kończy się null

Więc próbuję ustalić, jaka lista parametrów będzie miała strcpy_mine.

Próbowałem:

void strcpy_mine(char* pTarget, const char* const pCopyMe) 
{ 
    const unsigned int lenAlwaysFour = sizeof(pCopyMe); //:(
    strncpy(pTarget, pCopyMe, lenAlwaysFour); 

    //add extra terminator in case of overrun 
    pTarget[lenAlwaysFour] = 0; 
} 

ale sizeof jest zawsze 4 pCopyMe jest wskaźnikiem

czego nie chcesz zrobić, to wymienić

strcpy (buf, pCopyMe); 

z

strncpy (buf, pCopyMe, sizeof(pCopyMe)); buf[sizeof(pCopyMe)] = 0; 

jakieś pomysły? (Strcpy_l nie jest dostępny)

zdrowie

Odpowiedz

4

zależności od sposobu call-strony wyglądają, często większości przypadków mogą być obsługiwane za pomocą prostego szablonu:

#include <string.h> 

template <int bufferSize> 
void strcpy_mine(char (&pTarget)[bufferSize], const char* const pCopyMe) 
{ 
    strncpy(pTarget, pCopyMe, bufferSize-1); 

    //add extra terminator in case of overrun 
    pTarget[bufferSize-1] = 0; 
} 

int main() 
{ 
    char buf[128]; 
    strcpy_mine(buf,"Testing"); 
    return 0; 
} 

Jeśli używasz Microsoft Visual Studio 2005 lub nowszego, patrz Secure Template Overloads do implementacji Microsoft .

+0

okrzyki!to jest prawie to, czego szukam, ale nadal zmusza mnie do umieszczenia rozmiaru bufora w znakach szewronowych, chociaż jest to buf [200]; strcpy_mine <200> (buf, pString); – timB33

+0

strCpyMine (buf, pString); – timB33

+0

Potem robisz coś złego. Przestarzały kompilator? – MSalters

11

sizeof() zwraca rozmiar typu - w tym przypadku const char* const który będzie 4 w maszynach 32-bitowych.

Myślę, że uważasz, że chcesz strlen(). Ale to nie jest właściwy sposób korzystania z funkcji strncpy. Potrzebujesz rozmiaru bufora wyjściowego dla strncpy.

Aby to naprawić, należy sprawdzić kod w każdej witrynie wywołania i określić rozmiar bufora wyjściowego, a następnie przekazać go jako argument do strcpy_mine. Jeśli strona wywołania dla strcpy (lub strcpy_mine) nie zna rozmiaru bufora wyjściowego, musisz przeszukać wstecz w kodzie lokalizacji, która alokuje bufor, i przekazać rozmiar aż do strony strcpy .

Zasadniczo nie można napisać kropli zastępującej dla strcpy, która pobiera te same argumenty i ma nadzieję uniknąć problemów, które spowodowały strncpy w pierwszej kolejności (i lepszych zamienników poza tym). Możesz utworzyć funkcję, która przyjmuje takie same argumenty jak strncpy, ale zapewnia, że ​​wynik jest zakończony null - spójrz na implementację funkcji OpenBSD's strlcpy(). Ale pierwszym krokiem musi być zmiana stron wywołujących, aby przekazać wiedzę o wielkości bufora wyjściowego.

+0

+1 dla strlcpy. Pisząc własną funkcję podobną do tej, przekazuję również enum {AllOrNothing, TruncateOkay} do funkcji, która ma obsłużyć przypadki przepełnienia. – Dolphin

1

Możesz użyć tej samej listy parametrów, co strncpy dla swojej strcpy_mine, ale zapisz ją, aby zawsze zerwać wynik. Nie powinno to być trudne.

Jednym z wyzwań jest jednak to, że niektóre z istniejących kodów wywołujących funkcję strcpy() mogą nie znać wielkości bufora.

+0

Po drugie. Będziesz musiał dodać kolejny parametr wielkości bufora wyjściowego. Metoda strcpy jest klasycznym źródłem błędów przepełnienia bufora. Microsoft nawet wycofał tę funkcję na rzecz czegoś takiego jak strncpy. – Mark

0

Można również użyć makr, aby uniknąć wielu edycji. Lub zautomatyzuj edycję za pomocą jakiegoś skryptu.

+0

Jeśli Ci zależy, makro jest pojedyncze, makra to liczba mnoga. Macroses nie jest słowem. Zgaduję, że angielski nie jest twoim ojczystym językiem. Próbuję ci tylko pomóc. – jmucchiello

0

Zdecydowanie trzeba podać rozmiar bufora docelowego jako parametru, jak powiedzieli inni.

Jest to rodzaj off-topic, ale po prostu chcę podkreślić, że po użyciu strncpy(), trzeba ustawić na null ostatni znak w buforze, który posiada indeks 1 mniej niż długość (nie długość bufora):

strncpy (buf, pCopyMe, buflen); buf[buflen - 1] = '\0'; 

lub alternatywnie można użyć strncat() na pusty ciąg, przekazując jej długość, która jest o 1 mniejszy, a to gwarantuje null zakończyć swój ciąg:

buf[0] = '\0'; strncat (buf, pCopyMe, buflen - 1); 
+0

jeśli tak, to dlaczego nie: strncpy (buf, pCopyMe, buflen) [buflen-1] = '\ 0'; :-) –

+0

@Anders: Cool !!! – jmucchiello

0

Douglas Leeder ma to prawo. Istnieje pewna granica przydatności do zastąpienia strcpy, chyba że jesteś gotów wykonać gruntową pracę polegającą na przekazywaniu dobrej, rozsądnej długości bufora przy każdym wystąpieniu. To dużo pracy!

Dobra wiadomość jest taka, że ​​warto! Kilka lat temu wróciłem do kilku projektów C++, które były spóźnione, błędne i niewiarygodne. Deklarując, że strcpy i strlen są zabronione, i biorąc 2-3 dni z projektu na zastąpienie ich niestandardowymi strncpy/strnlen, we wszystkich tych projektach mogliśmy nagle działać przez kilka dni zamiast godzin. Widzieliśmy również wiele obciętych łańcuchów wychodzących na ekrany i pliki dziennika. Dostarczyło nam to wskazówek potrzebnych do wyśledzenia problemów związanych z przycinaniem, które wcześniej powodowały awarie.

Jeśli nie chcesz tego zrobić, możesz uzyskać znacznie mniejsze korzyści, po prostu sprawdzając oba parametry wskaźnika dla wartości NULL i ograniczając maksymalny rozmiar kopii ciągu i rejestrując cały czas, że granica jest osiągnięta. Nie rób żadnego z tych parametrów, ponieważ strlen z przyjemnością spadnie na ciebie, jeśli łańcuch nie zostanie poprawnie zakończony.

Obecnie nowe projekty korzystają z dobrych obiektów napisowych, ale istnieje wiele starszych kodów, które nie istnieją.

2

Może trochę peryferyjnie, ale ponieważ nikt o tym nie wspomniał i jest obnoszony w tytule: nie możesz (prawnie) napisać globalnej funkcji o nazwie strcpy_mine().

"Przestrzeń nazw" funkcji, których nazwy zaczynają się od str jest zarezerwowana dla biblioteki standardowej. Zobacz na przykład the accepted answer to this question.

+0

ciekawe, okrzyki :) – timB33