Можно обойти это при помощи класса черт:
Это требует, чтобы Вы настроили specialsed класс черт для каждого фактического класса, который Вы используете.
template<typename SubClass>
class SubClass_traits
{};
template<typename Subclass>
class A {
public:
void action(typename SubClass_traits<Subclass>::mytype var)
{
(static_cast<Subclass*>(this))->do_action(var);
}
};
// Definitions for B
class B; // Forward declare
template<> // Define traits for B. So other classes can use it.
class SubClass_traits<B>
{
public:
typedef int mytype;
};
// Define B
class B : public A<B>
{
// Define mytype in terms of the traits type.
typedef SubClass_traits<B>::mytype mytype;
public:
B() {}
void do_action(mytype var) {
// Do stuff
}
};
int main(int argc, char** argv)
{
B myInstance;
return 0;
}
Используете ли вы Xcode 3.1 на Snow Leopard? У меня та же проблема:
CGContextRef ctx = ...;
CGImageRef cgImage = CGBitmapContextCreateImage(ctx);
UIImage * newImage = [[UIImage imageWithCGImage:cgImage] retain];
CGImageRelease(cgImage); // this should be OK, but it now crashes in Simulator on SL
Я предполагаю, что обновление до Xcode 3.2 устранит проблему.
)) / что бы то ни было, реализация strncat может быть оптимизирована для целевой платформы / платформы в библиотеке.Конечно, вам нужно проверить, что dst содержит хотя бы nullchar, поэтому правильное использование strncat будет примерно таким:
if(LEN) { *dst = '\0'; strncat(dst, src, LEN-1); }
Я также признаю, что strncpy не очень полезен для копирования подстроки в другую строку, если src короче n символов, строка назначения будет обрезана.
Уже существуют реализации с открытым исходным кодом, такие как strlcpy , которые делают безопасное копирование.
http://en.wikipedia.org/wiki/Strlcpy
В ссылки есть ссылки на источники.
Учтите:
Именно этого можно было бы достичь с помощью:
strncpy(inode->d_name, filename, 14);
Итак, strncpy ()
идеально подходил для своей первоначальной ниши. Это было лишь случайным совпадением относительно предотвращения переполнения строк с завершающим нулем.
(Обратите внимание, что заполнение нулями до длины 14 не является серьезными накладными расходами - если длина буфера составляет 4 КБ и все, что вам нужно, это безопасно скопировать 20 символов в него, то лишние 4075 нулей - серьезный перебор,
Некоторые новые альтернативы указаны в ISO / IEC TR 24731 (см. https://buildsecurityin.us-cert.gov/daisy/bsi/articles/knowledge/coding/317- BSI.html для информации). Большинство этих функций принимают дополнительный параметр, определяющий максимальную длину целевой переменной, гарантирующий, что все строки заканчиваются нулем и имеют имена, заканчивающиеся на _s
(для «безопасности»?), Чтобы различать их. из их более ранних «небезопасных» версий. 1
К сожалению, они все еще получают поддержку и могут быть недоступны с вашим конкретным набором инструментов. Более поздние версии Visual Studio будут выдавать предупреждения, если вы используете старые небезопасные функции.
Если ваши инструменты не поддерживают новые функции, будет довольно легко создать свои собственные оболочки для старых функций. . Вот пример:
errCode_t strncpy_safe(char *sDst, size_t lenDst,
const char *sSrc, size_t count)
{
// No NULLs allowed.
if (sDst == NULL || sSrc == NULL)
return ERR_INVALID_ARGUMENT;
// Validate buffer space.
if (count >= lenDst)
return ERR_BUFFER_OVERFLOW;
// Copy and always null-terminate
memcpy(sDst, sSrc, count);
*(sDst + count) = '\0';
return OK;
}
Вы можете изменить функцию в соответствии со своими потребностями, например, чтобы всегда копировать как можно большую часть строки без переполнения. Фактически, реализация VC ++ может сделать это, если вы передадите _TRUNCATE
в качестве счетчика
.
strcpy_s()
, что в нем есть место для 25 символов, у вас все равно проблемы. Strncpy более безопасен против атак переполнения стека со стороны пользователя вашей программы, он не защищает вас от ошибок вы программист, например как печать строки без завершающего нуля, как вы описали.
Вы можете избежать сбоя из-за проблемы, которую вы описали, ограничив количество символов, выводимых printf:
char my_string[10];
//other code here
printf("%.9s",my_string); //limit the number of chars to be printed to 9
Используйте strlcpy ()
, указанный здесь: http://www.courtesan.com/todd/papers/strlcpy.html
Если ваш libc не имеет реализации, тогда попробуйте эту:
size_t strlcpy(char* dst, const char* src, size_t bufsize)
{
size_t srclen =strlen(src);
size_t result =srclen; /* Result is always the length of the src string */
if(bufsize>0)
{
if(srclen>=bufsize)
srclen=bufsize-1;
if(srclen>0)
memcpy(dst,src,srclen);
dst[srclen]='\0';
}
return result;
}
(Написано мной в 2004 году - посвящено общественному достоянию)
strncpy работает напрямую с доступными строковыми буферами, если вы работаете напрямую со своей памятью, вы ДОЛЖНЫ теперь размеры буфера, и вы можете установить '\ 0' вручную.
Я полагаю, что есть не лучшая альтернатива в простом C, но на самом деле это не так уж плохо, если вы будете настолько осторожны, как должны, при игре с сырой памятью.
Я всегда предпочитал:
memset(dest, 0, LEN);
strncpy(dest, src, LEN - 1);
исправить это позже, но на самом деле это всего лишь вопрос предпочтений.
Не полагаясь на новые расширения, я делал что-то подобное в прошлом:
/* copy N "visible" chars, adding a null in the position just beyond them */
#define MSTRNCPY( dst, src, len) ( strncpy( (dst), (src), (len)), (dst)[ (len) ] = '\0')
и, возможно, даже:
/* pull up to size - 1 "visible" characters into a fixed size buffer of known size */
#define MFBCPY( dst, src) MSTRNCPY( (dst), (src), sizeof( dst) - 1)
Почему макросы вместо более новых «встроенных» (?) функции? Потому что раньше было довольно много разных юниксов, а также других сред, отличных от unix (не Windows), которые мне приходилось переносить обратно, когда я ежедневно делал C.
Эти функции эволюционировали больше, чем разрабатывались, поэтому на самом деле нет никакого «почему». Вам просто нужно научиться «как». К сожалению, справочные страницы Linux по крайней мере лишены распространенных примеров использования этих функций, и я заметил много злоупотреблений в коде, который я рассмотрел. Я сделал несколько заметок здесь: http://www.pixelbeat.org/programming/gcc/string_buffers.html
Вместо strncpy ()
вы можете использовать
snprintf(buffer, BUFFER_SIZE, "%s", src);
Вот однострочник, который копирует не более size-1
ненулевых символов от src
до dest
и добавляет нулевой терминатор:
static inline void cpystr(char *dest, const char *src, size_t size)
{ if(size) while((*dest++ = --size ? *src++ : 0)); }