Как использовать функцию strncpy_s из Visual C ++? - PullRequest
0 голосов
/ 16 февраля 2012

Я изучаю некоторые новые вещи в C ++, и я пытался протестировать эту функцию strncpy_s из Visual C ++.Однако я сталкиваюсь с некоторыми проблемами, когда происходит сбой программы, и я не знаю, что происходит, но я уверен, что это довольно глупая проблема.Исходный код выглядит примерно так:

#include "stdafx.h"
#include <iostream>
#include <cstdio>
#include <cstring>

int main()
{
    char *p;
    p=(char *)malloc(sizeof(char)*strlen("Hello!\n"));
    strncpy_s(p,strlen("Hello!\n"),"Hello!\n",strlen("Hello!\n"));
    std::cout << p;
    std::cout << strlen("Hello!\n") << std::endl;
    return 0;
}

Как я уже сказал, я не использую std :: string coz. Я хочу попробовать эту новую функцию и узнать, как она работает.

Ответы [ 6 ]

2 голосов
/ 16 февраля 2012

Строковые функции с расширенной безопасностью в основном предназначены для аварийного завершения работы при возникновении проблемы.

Из Документы Microsoft по strncpy_s():

Эти функции пытаются скопировать первые D символов strSource в strDest, где D - это меньшее число и длина strSource.Если эти символы D поместятся в strDest (размер которого указан как numberOfElements) и все еще оставляют место для нулевого терминатора, то эти символы копируются, и добавляется завершающий ноль;в противном случае strDest [0] устанавливается в нулевой символ и вызывается недопустимый обработчик параметров, как описано в разделе Проверка параметров.

Существует исключение из вышеприведенного абзаца.Если count равен _TRUNCATE, то копируется столько strSource, сколько уместится в strDest, оставляя место для завершающего нуля, который всегда добавляется.

Описание проверки параметров is:

Поведение C Runtime при обнаружении недопустимого параметра заключается в вызове назначенного в данный момент недопустимого обработчика параметров.Недопустимый параметр по умолчанию вызывает отчет о сбоях Watson, который вызывает сбой приложения и запрашивает у пользователя, хотят ли они загрузить дамп сбоя в Microsoft для анализа.В режиме отладки неверный параметр также приводит к ошибочному утверждению.

Это поведение можно изменить с помощью функции _set_invalid_parameter_handler, чтобы установить для обработчика недопустимого параметра свою собственную функцию....

Ваш пример программы предоставляет буфер, который слишком мал на единицу char (нет места для нулевого терминатора).

Так что, если вы не измените то, что следуетпроизойдет, когда функции strxxxx_s произойдут, когда возникнет ошибка, ваша программа будет аварийно завершена.Идея состоит в том, что сбой лучше, чем ошибка, которая может открыть дыру в безопасности.

2 голосов
/ 16 февраля 2012

Я забираю свои комментарии, я читаю документацию более внимательно. Ваш код передает недопустимые параметры и вызывает обработчик недопустимых параметров. Может быть, это то, что происходит. А именно:

p=(char *)malloc(sizeof(char)*strlen("Hello!\n"));

Эта строка выделяет место для 7 символов, то есть длины строки, но недостаточно места для нулевого терминатора . (Это вообще ошибка)

Документация для strncpy_s гласит: Эти функции пытаются скопировать первые D символов strSource в strDest, где D - это меньшее из количества и длины strSource. Если эти символы D будут соответствовать в пределах strDest (размер которого указан как numberOfElements) и все еще оставлять место для нулевого терминатора , то эти символы копируются, и завершающий ноль добавляется; в противном случае strDest [0] устанавливается в нулевой символ, и вызывается недопустимый обработчик параметра , как описано в разделе Проверка параметров.

Возможно, вы видите "недопустимый обработчик параметров"?

2 голосов
/ 16 февраля 2012

Вам нужен еще 1 символ для завершающего символа ('\0'), поэтому вам нужно заменить strlen("Hello!\n") на strlen("Hello!\n") + 1.Вы можете сохранить эту длину в некоторой переменной вместо повторного вызова strlen.Кроме того, поскольку вы используете C ++, вы можете использовать new / delete вместо malloc / free:

int len = strlen("Hello!\n") + 1;
char *p;
p = new char[len];
strncpy_s(p, len, "Hello!\n", len);
std::cout << p << len << std::endl;
delete[] p;
1 голос
/ 16 февраля 2012

Вам нужно выделить strlen ("Hello! \ N") + 1 (для нулевого терминатора). И sizeof (char) совершенно бессмысленен, поскольку sizeof (char) гарантированно будет равен 1 на всех платформах.

1 голос
/ 16 февраля 2012

strlen(s) сообщит вам только длину строки без NUL-терминатора. Чтобы выделить место для копирования строки, вы обычно используете strlen(s)+1, чтобы добавить пространство для терминатора NUL.

0 голосов
/ 16 февраля 2012

Почему вы используете malloc или char *, если вы используете C ++?

std::string p = "Hello!\n";
std::cout << p;
std::cout << p.length();

или

std::string* p = new std::string("Hello!\n");
std::cout << p;
std::cout << p->length();

Но чтобы ответить на ваш оригинальный вопрос, вам, вероятно, нужно использовать strlen(p) + 1

А если вам нужен символ * из вашей строки, вы можете использовать p.c_str()

...