PDA

View Full Version : خطای strcpy در ویژال استدیو 2012



hosseinam1370
جمعه 24 بهمن 1393, 14:15 عصر
دوستان من از تابع strcpy استفاده کردم و اینکلودهاش هم درسته ، اما باز این خطا رو میده ،
http://upload7.ir/uploads//6ee8bfa7ca47bfc663752220acce51114a901bdf.png

اینم کدش :

void convert ( int*h , char* time)
{
if (*h <= 12)
strcpy(time , "AM");
else
{
*h-=12;
strcpy(time , "PM");
}
}

اینم اینکلودهاش:

#include "stdafx.h"
#include <iostream>
#include <string.h>
using namespace std;

چطور باید حل شه؟

قبلا فکر کنم یه چیزی به کد اضافه میکردم و حل میشد، الان دیگه به ذهنم نمیرسه و چرا اضافه میکردم هم نمیدونم.


با تشکر.

rm classic
چهارشنبه 29 بهمن 1393, 19:42 عصر
^^^^^^strcpy_s^^^^^^

[[[[[[[[[[...]]]]]]]]]]
چهارشنبه 29 بهمن 1393, 20:15 عصر
strcpy تابع امنی نیست. اگر برنامه نویس اندازه بافر متغیر مقصد رو به اندازه ای تایین نکنه که بتونه عناصر داخل متغیر منبع رو در خودش جای بده، بنابراین بافر مقصد سَرریز می کنه.
به همین منظور، شرکت Microsoft نسخه ای نسبتا امنیتی از strcpy به نام strcpy_s رو عرضه کرد.

پارامتر جدیدی در تابع strcpy_s به نام nSize از نوع size_t به منظور 'تایین اندازه بافر متغیر مقصد توسط برنامه نویس' اضافه شده.
متغیر مقصد حداکثر nSize فضا برای ذخیره عناصر منبع داره.

این تابع رو با strncpy اشتباه نگیر; در تابع strcpy_s متغیر nSize نقش اندازه بافر متغیر مقصد رو داره. در صورتی که متغیر n در تابع strncpy تعداد عناصری رو که قراره از متغیر منبع به مقصد کپی بشن رو مشخص می کنه.

به نظر من هر تابعی که پارامتری از نوع unsigned داشته باشه نا امنه; کافیه که چنین تابعی آرگومانی کمتر از 0 از طریق پارامتری که انتظار داره آرگومانش حداقل 0 باشه رو دریافت کنه تا برنامه با خطا رو به رو بشه.
پارامترهای نوع int یا long رو بهتر میشه خطایابی کرد، اما ممکنه کلی مزایا از دست بدیم. من از هر نوع unsigned متنفرم.

می تونی از strcpy_s در برنامه ات استفاده کنی: strcpy_s, wcscpy_s, _mbscpy_s (https://msdn.microsoft.com/en-us/library/td1esda9.aspx) یا خودت یک نسخه امن از strcpy و strncpy و دیگر توابع نا امن بنویسی.

بافر متغیر destination در برنامه زیر سَرریز می کنه و strcpy نمی تونه کاری انجام بده:






#include <stdio.h> /* For int puts (const char*) */
#include <stdlib.h> /* For void exit (int), EXIT_FAILURE */
#include <string.h> /* For void *memset (void*, int, size_t), char *strcpy (char*, const char*) */

#define DEST_BUFFSIZ 512+1
#define SRC_BUFFSIZ 1024+1

int main ()
{
char destination[DEST_BUFFSIZ];
char source[SRC_BUFFSIZ];

memset (destination, '\0', DEST_BUFFSIZ);
memset (source, '\0', SRC_BUFFSIZ);

memset (source, 'c', SRC_BUFFSIZ-1); /* source[0] ... source[SRC_BUFFSIZ-2] */

strcpy (destination, source);

exit (EXIT_FAILURE); /* exits the program/returns the failure signal to the OS (if called up) */
}

[[[[[[[[[[...]]]]]]]]]]
پنج شنبه 30 بهمن 1393, 21:31 عصر
فراموش کرده بودم راجع به تابع ات نظر بدم.



void convert ( int*h , char* time)
{
if (*h <= 12)
strcpy(time , "AM");
else
{
*h-=12;
strcpy(time , "PM");
}
}




تو نوشتی: اگر h به متغیری حاویِ مقداری بزرگتر از 12 اشاره می کنه، 12تا از مقدار اون متغیر کم کن و باقی مانده رو در اون ذخیره کن. بدین صورت ساعت 1PM میشه، اما ساعت/دور بعد که تابع ات صدا زده میشه، شرط اول درسته، پس AM جای PM قرار می گیره، چون مقدار متغیری که h در حال اشاره کردن به اون هست، کمتر از 12 هست (یعنی 2)، در صورتی که 1 ساعت پیش دوره بعد از ظهر شروع شده بود! گذشته از این، دوره بعد از ظهر باید از 12PM شروع بشه نه 1PM.

اگر ساعت رو از 12 شروع کنیم، نتیجه کار تابع تو میشه:


12AM - 1PM - 2...12AM - 1PM - 2...12AM


اگر از 1 شروع کنیم:



1...12AM - 1PM - 2...12AM - 1PM - 2...12AM - 1PM




اصلا لازم نیست که مقدار ساعت رو در تابعی دستکاری کنی. M که ثابته، بنابراین بهتر نیست که فقط A رو جای P یا بلعکس قرار بدی؟ می تونی این کار رو هر 12 ساعت انجام بدی.

با توجه به تابع تو، 12PM اصلا وجود نخواهد داشت.

لازم نیست از تابع strcpy استفاده کنی، چون راه سریعتری وجود داره. با توجه به اینکه (period+1)* همیشه M هست، تنها کافیه روی period* اعمال تغییر کنی: A به P و P به A.