Подтвердить что ты не робот

Есть ли безопасная версия strlen?

std:: strlen не обрабатывает строки c, которые не завершены \0. Есть ли безопасная версия?

PS Я знаю, что в С++ std::string следует использовать вместо строк c, но в этом случае моя строка хранится в общей памяти.

ИЗМЕНИТЬ

Хорошо, мне нужно добавить некоторые объяснения.

Мое приложение получает строку из разделяемой памяти (которая имеет некоторую длину), поэтому ее можно представить в виде массива символов. Если в библиотеке есть ошибка, записывающая эту строку, тогда строка не будет завершена нулем, а strlen может выйти из строя.

4b9b3361

Ответ 1

Если вы определяете c-строку как

char* cowSays = "moo";

тогда вы автоматически получите "\ 0" в конце и strlen вернется 3. Если вы определите его как:

char iDoThis[1024] = {0};

вы получаете пустой буфер (и массив символов, все из которых являются пустыми символами). Затем вы можете заполнить его тем, что вам нравится, если вы не превысите длину буфера. В начале strlen вернется 0, и как только вы написали что-то, вы также получите правильный номер от strlen.
Вы также можете сделать это:

char uhoh[100];
int len = strlen(uhoh);

но это было бы плохо, потому что вы не знаете, что находится в этом массиве. Он может ударить нулевого символа, которого вы не можете. Дело в том, что нулевой символ является стандартным стандартным, чтобы объявить, что строка закончена.
Не имеющий нулевого символа означает по определению, что строка не закончена. Изменение, которое нарушит парадигму работы струны. Что вы хотите сделать, это составить свои собственные правила. С++ позволит вам это сделать, но вам придется писать много кода самостоятельно.

ИЗМЕНИТЬ Из вашей недавно добавленной информации то, что вы хотите сделать, - это цикл над массивом и проверка нулевого символа вручную. Вы также должны сделать некоторую проверку, если вы ожидаете только символов ASCII (особенно если вы ожидаете буквенно-цифровых символов). Это предполагает, что вы знаете максимальный размер. Если вам не нужно проверять содержимое строки, вы можете использовать одно из семейств функций strnlen: http://msdn.microsoft.com/en-us/library/z50ty2zh%28v=vs.80%29.aspx
http://linux.about.com/library/cmd/blcmdl3_strnlen.htm

Ответ 2

Вы добавили, что строка находится в общей памяти. Это гарантированное читабельность и фиксированный размер. Поэтому вы можете использовать size_t MaxPossibleSize = startOfSharedMemory + sizeOfSharedMemory - input; strnlen(input, MaxPossibleSize) (помните о дополнительном n в strnlen).

Это вернет MaxPossibleSize, если в общей памяти, следующей за input, нет \0, или длина строки, если она есть. (Максимально возможная длина строки, конечно, MaxPossibleSize-1, если последний бит общей памяти является первым \0)

Ответ 3

Строки C, которые не имеют нулевого конца, не являются строками C, они просто массивы символов, и нет способа найти их длину.

Ответ 4

size_t safe_strlen(const char *str, size_t max_len)
{
    const char * end = (const char *)memchr(str, '\0', max_len);
    if (end == NULL)
        return max_len;
    else
        return end - str;
}

Ответ 5

Получить лучшую библиотеку или проверить ее, если вы не можете доверять своей библиотеке, чтобы делать то, что она говорит, а затем как h% ^ и вы ожидаете от своей программы?

Thats said: Предполагая, что вы знаете длину buiffer, строка находится, как насчет

buffer[-1+sizeof(buffer)]=0 ;
 x = strlen(buffer) ; 
  • сделать буфер больше, чем необходимо, и затем вы можете протестировать lib.

    assert(x<-1+sizeof(buffer));
    

Ответ 6

Вам нужно будет закодировать вашу строку. Например:

struct string
{
    size_t len;
    char *data;
} __attribute__(packed);

Затем вы можете принять любой массив символов, если знаете, что первые байты sizeof (size_t) для разделяемой памяти - это размер массива char. Это становится сложно, если вы хотите связать массивы таким образом.

Лучше доверять другому концу, чтобы прервать его или перевернуть собственный strlen, который не выходит за пределы бестселлеров сегмента разделяемой памяти (предоставляя вам знать, по крайней мере, размер этого сегмента).

Ответ 7

Если вам нужно получить размер разделяемой памяти, попробуйте использовать

// get memory size
struct shmid_ds shm_info;
size_t shm_size;
int shm_rc;
if((shm_rc = shmctl(shmid, IPC_STAT, &shm_info)) < 0)
    exit(101);
shm_size = shm_info.shm_segsz;

Вместо использования strlen вы можете использовать shm_size - 1, если вы уверены, что оно завершено нулем. В противном случае вы можете обнулить его данными [shm_size - 1] = '\ 0'; затем используйте strlen (data);

Ответ 8

простое решение:

buff[BUFF_SIZE -1] = '\0'

ofc это не скажет вам, что строка первоначально была точно BUFF_SIZE-1 долго или она просто не была завершена... так что для этого вам нужна логика xtra.

Ответ 9

Как насчет этого портативного самородок:

int safeStrlen(char *buf, int max)
{
   int i;
   for(i=0;buf[i] && i<max; i++){};
   return i;
}

Ответ 10

Как Нил Баттерворт уже сказал в своем ответе выше: C-строки, которые не заканчиваются символом \0, не являются C-Strings!

Единственный шанс, который у вас есть, это написать неизменяемый адаптер или что-то, что создает допустимую копию C-String с символом завершения \0. Конечно, если вход неверен и существует C-строка, определенная как:

char cstring[3] = {'1','2','3'};

действительно приведет к неожиданному поведению, потому что в памяти теперь может быть что-то вроде [email protected]\0. Таким образом, результат strlen(), например, теперь равен 6, а не 3, как ожидалось.

Следующий подход показывает, как создать безопасную C-строку в любом случае:

char *createSafeCString(char cStringToCheck[]) {
    //Cast size_t to integer
    int size = static_cast<int>(strlen(cStringToCheck)) ;
    //Initialize new array out of the stack of the method
    char *pszCString = new char[size + 1];
    //Copy data from one char array to the new
    strncpy(pszCString, cStringToCheck, size);
    //set last character to the \0 termination character
    pszCString[size] = '\0';
    return pszCString;
}

Это гарантирует, что если вы будете манипулировать C-String, чтобы не писать в памяти что-то еще.

Но это не то, что вы хотели. Я знаю, но нет другого пути для достижения длины массива char без завершения. Это даже не подход. Это просто гарантирует, что даже если пользователь (или Dev) вставляет *****, чтобы нормально работать.