Heap error in VS2010 - c++

I'm trying to implement the program, which recognizes Windows file attributes. I have a code, but sometimes, I receive heap error after passing return in the main block. Thank you for your attention and help!
#include "stdafx.h"
#include <Windows.h>
#include <conio.h>
_TCHAR* getStringAttributes(int value, _TCHAR* str[])
{
DWORD d = GetFileAttributes(str[value]);
_TCHAR* temp;
switch(d)
{
case 2048: temp = L"Compressed\n"; break;
case 32: temp = L"Archive\n"; break;
case 16: temp = L"Directory\n"; break;
case 16384: temp = L"Encrypted\n"; break;
case 2: temp = L"Hidden\n"; break;
case 128: temp = L"Normal\n"; break;
case 1: temp = L"Readonly\n"; break;
case 4: temp = L"System\n"; break;
case 256: temp = L"Temporary\n"; break;
default: temp = L"Error or unsupported attribute\n"; break;
}
return temp;
}
int _tmain(int argc, _TCHAR* argv[])
{
_TCHAR* attString = new _TCHAR();
char* ynAnswer = new char();
if(argv[1] == NULL)
{
printf("%s\n","You didn't type file path. Try again?[Y/N]");
gets_s(ynAnswer,10);
if(*ynAnswer == 'y' || *ynAnswer == 'Y')
{
printf("%s\n","Type in a path to the file");
argv[1] = new _TCHAR();
_getws(argv[1]);
if(argv[1] != L"")
{
printf("%s","Attribute: ");
attString = getStringAttributes(1,argv);
_tprintf(attString);
printf("%s","for\n");
_tprintf(argv[1]);
}
}
}
else
{
printf("%s","Attribute: ");
attString = getStringAttributes(1,argv);
_tprintf(attString);
}
printf("%s","Goodbye");
getch();
delete[] ynAnswer;
delete[] attString;
return 0;
}

you input whole string into 1 or 2 bytes strings.
These allocations:
_TCHAR* attString = new _TCHAR();
char* ynAnswer = new char();
Allocate only 1 item array.
it should be:
_TCHAR* attString = new _TCHAR[MAX_SIZE];
char* ynAnswer = new char[MAX_SIZE];
When MAX_SIZE must beeb defuned as macro.
even better is to use:
wstring attString ;
string ynAnswer;
wcin>> attString;
cin>> ynAnswer;
More problem is the allocation in the line:
argv[1] = new _TCHAR();
in addition to the previous answered problem, in this line argv[1] may not even exists.
You should input to other buffer.
it can be like this:
wstring argv1;
if(argc <2){
wcin>>argv1;
}else{
argv1=argv[1];
}
now use argv1 instead of argv[1]
One more thing:
You are using _TCHAR as WCHAR.
when you use _TCHAR strings should be decalared as:
_T("some string")
not as:
L"some string".

Related

dynamic 2d char array in c

I want to take username and passwords from client and check that this username already didn't exist, but it doesn't work and this error happens:
Exception thrown at 0x51D20ED2 (ucrtbased.dll) in project3.exe: 0xC0000005:
Access violation reading location 0xCDCDCDCD.>
I don't know why?
This is my code:
void signup(char *input, char **usernames,int *userindex,char **passwords)
{
int check = 0;
char *ptr1,*ptr2;
ptr1 = (char*)malloc(strlen(input)*sizeof(char));
ptr2 = (char*)malloc(strlen(input)*sizeof(char));
strtok(input, " ");
strcpy(ptr1, strtok(NULL," "));
strcpy(ptr2, strtok(NULL," "));
for (int i = 1; i < *(userindex); i++)
{
if (!(strcmp(ptr1,usernames[i])))
{
check = 1;
printf("this user has already signed up\n");
break;
}
}
if (check == 0)
{
usernames[*(userindex)] = (char*)malloc((strlen(ptr1))* sizeof(char));
passwords[*(userindex)] = (char*)malloc((strlen(ptr2))* sizeof(char));
strcpy(usernames[*(userindex)], ptr1);
strcpy(passwords[*(userindex)], ptr2);
printf("%s\n%s\n%d\n", usernames[*(userindex)], passwords[*(userindex)], *(userindex));
*(userindex) = *(userindex)+1;
free(ptr1);
free(ptr2);
}
}
int main()
{
int quit = 0;
char *input, **usernames, **passwords;
int state, length, userindex = 1;
usernames = (char**)malloc(sizeof(char*));
passwords = (char**)malloc(sizeof(char*));
while (quit == 0)
{
int counter = 1;
char buffer;
input = (char*)malloc(sizeof(char));
printf("please enter your action\n");
do
{
buffer = getchar();
input = (char*)realloc(input, counter*sizeof(char));
input[counter - 1] = buffer;
counter++;
} while (buffer != '\n');
input = (char*)realloc(input, (counter)*sizeof(char));
input[counter - 1] = '\0';
state = action_decider(input);
switch (state)
{
case 0:
break;
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
usernames = (char**)realloc(usernames,userindex*sizeof(char*));
passwords = (char**)realloc(passwords,userindex*sizeof(char*));
signup(input, usernames, &(userindex), passwords);
break;
case 5:
break;
case 6:
quit = 1;
break;
case 7:
printf("you command nonsence!\n");
break;
}
}
return 0;
}

c++ caesar cipher program executes wrong character

Here is what I get when I try to encrypt "This is a test sentence!": "Ymnxp���p�����t�������"
I have tested my encryption part before and it worked fine.
Can anyone please tell me what did I do wrong here?
#include <iostream>
#include <string>
#include <fstream>
#include <stdlib.h>
#include <stdio.h>
#include "unistd.h"
using namespace std;
void displayUsage(){
// Displays how to use this program
// TODO
cout << "Instruction: \n use -r to give rotation number \n use -f to give file name" <<endl;
}
int main(int argc, char **argv){
string text;
char* input_file_name;
int rotation;
bool have_rotation = false;
bool have_input_file_name = false;
// process command-line arguement
int opt = 0;
extern char *optarg;
static const char* opt_string = "r:f:";
opt = getopt( argc, argv, opt_string);
while(opt != -1) // While there are parameters to parse, do so
{
switch(opt)
{
case 'r':
have_rotation = true;
rotation = atoi(optarg);
break;
case 'f':
have_input_file_name = true;
input_file_name = optarg;
break;
default:
displayUsage();
return 1;
}
opt = getopt( argc, argv, opt_string); // Pull the next parameter, or 0 if none.
}
if(!have_rotation)
{
displayUsage();
return 0;
}
if(have_rotation)
{
if(have_input_file_name)
{
ifstream file(input_file_name);
string text2, temp;
while(!file.eof())
{
getline(file, temp);
text2 += temp;
text2 += "\n";
}
text = text2[text2.size()-2];
}
else
{
cout <<"Enter text:"<<endl;
cin >> text;
}
}
char cipher[text.size()];
for(int i=0; i<text.size(); i++)
{
cipher[i] = text[i];
if(islower(cipher[i]))
{
cipher[i] = (cipher[i] - 'a' + rotation)%26 + 'a';
}
else if(isupper(cipher[i]))
{
cipher[i] = (cipher[i] - 'A' + rotation)%26 + 'A';
}
}
cout <<cipher<<endl;
return 0;
}
I guess the error is because you did not terminate your cipher array with a '\0'.
The printing function will process characters from an array (and possibly beyond) until it finds a '\0' character.
Your array should be one bigger to account for this terminating character.
Or get rid of the char array and use std::string.
I can get my code run if I type the sentence manually. It doesn't printout anything if I input a text file.
#include <iostream>
#include <string>
#include <fstream>
#include <stdlib.h>
#include <stdio.h>
#include "unistd.h"
using namespace std;
void displayUsage(){
// Displays how to use this program
// TODO
cout << "Instruction: \n use -r to give rotation number \n use -f to give file name" <<endl;
}
char caesar(char c, int r)
{
if(isalpha(c))
{
if(islower(c))
{
c = (((c-97)+r)%26)+97; // 97 is a value of 'a'
}
else if(isupper(c))
{
c = (((c-65)+r)%26)+65; // 65 is a value of 'A'
}
}
return c;
}
int main(int argc, char **argv){
string text;
char* input_file_name;
int rotation;
bool have_rotation = false;
bool have_input_file_name = false;
// process command-line arguement
int opt = 0;
extern char *optarg;
static const char* opt_string = "r:f:";
opt = getopt( argc, argv, opt_string);
while(opt != -1) // While there are parameters to parse, do so
{
switch(opt)
{
case 'r':
have_rotation = true;
rotation = atoi(optarg);
break;
case 'f':
have_input_file_name = true;
input_file_name = optarg;
break;
default:
displayUsage();
return 1;
}
opt = getopt( argc, argv, opt_string); // Pull the next parameter, or 0 if none.
}
if(!have_rotation)
{
displayUsage();
return 0;
}
if(have_rotation)
{
if(have_input_file_name)
{
ifstream file(input_file_name);
string text2, temp;
while(!file.eof())
{
getline(file, temp);
text2 += temp + "\n";
}
text = text2[text2.size()-2];
}
else
{
cout <<"Enter text:"<<endl;
getline(cin, text);
}
}
string output = "";
for(int i = 0; i < text.size(); i++)
{
output += caesar(text[i],rotation);
}
cout<<output<<endl;
return 0;
}

How send a structure through fifo

HI!
I am trying to pass whole structure from one program and read it in another using fifo.
I'm using read and write functions. I had a problem with putting my structure into this functions. When I did it and tried to send and receive I get an error (core dump) or I recived some trash. I dont know exactly, where my problem take place (in receiver or sender). How can I send/receive my structure, or what i have wrong in my code.Here is my code...Receiver
struct data
{
char* message;
int size;
vector <times> prog;
};
int if_fifo(char* name)
{
struct stat info;
int score = stat(name,&info);
if(S_ISFIFO(info.st_mode))
{
return 1;
}
else
{
return 0;
}
}
int fifo_in(char* name)
{
data msg;
int pip;
pip = open(name, O_RDONLY | O_NONBLOCK);
while(1)
{
int hr = read(pip,&msg,sizeof(msg));
if(hr != 0)
{
cout << "Message: " << msg.message << endl;
}
}
cout << "O.K." << endl;
return 0;
}
int main(int argc, char** argv) {
int c, status_in, status_out;
char* input;
char* output;
float del;
if(argc < 5)
{
cout << "Za malo podanych parametrow" << endl;
return 1;
}
else
{
while ((c = getopt(argc, argv, "iod:")) != -1)
{
switch (c)
{
case 'i':
input = argv[2];
status_in = if_fifo(input);
break;
case 'o':
output = argv[3];
status_out = if_fifo(output);
break;
case 'd':
del = atof(argv[4]);
break;
case '?':
printf("UKNOWN");
}
}
}
if(status_in == 1)
{
return fifo_in(input);
}
else
{
cout << "It isnt fifo!!" << endl;
}
return 0;
}
And sender:
struct data
{
char* message;
int size;
vector <times> prog;
}msg;
int if_fifo(char* name)
{
struct stat info;
int score = stat(name,&info);
if(S_ISFIFO(info.st_mode))
{
return 1;
}
else
{
return 0;
}
}
int fifo_out(char* name)
{
msg.message = "To jest to!!";
msg.size = sizeof(msg.message);
int pip;
pip = open(name, O_WRONLY);
if( pip == -1 )
{
perror("Error: open( ): ");
return 1;
}
write(pip,&msg,sizeof(msg));
return 0;
}
int main(int argc, char** argv) {
int c, status_out;
char* output;
if(argc < 3)
{
cout << "Za malo podanych parametrow" << endl;
return 1;
}
else
{
while ((c = getopt(argc, argv, "o:")) != -1)
{
switch (c)
{
case 'o':
output = argv[2];
status_out = if_fifo(output);
break;
case '?':
printf("UKNOWN");
}
}
}
if(status_out == 1)
{
return fifo_out(output);
}
return 0;
}
you cannot just send memory structures from one program to another. You have to do whats called 'serialization' ie convert the struct into a byte stream that represents the structure. There are many, many serialization techniques: ASN1/ Ber, XML, JSON, Google protocol buffs, roll your own.
Just so you know why this is. The field message in your struct is actually a pointer, when you send this pointer to another program it points to the same address but in the receiver prgram not the sender. That address likely doesnt exist and certainly does not contain the string you had in the sender program.

GetFileAttributes Function

#include "stdafx.h"
#include <Windows.h>
#include <conio.h>
int _tmain(int argc, _TCHAR* argv[])
{
DWORD d = GetFileAttributes(argv[0]);
_TCHAR* temp;
printf("%d\n", d);
switch(d)
{
case 2048: temp = L"Compressed"; break;
case 32: temp = L"Archive"; break;
case 16: temp = L"Directory"; break;
case 16384: temp = L"Encrypted"; break;
case 2: temp = L"Hidden"; break;
case 128: temp = L"Normal"; break;
case 1: temp = L"Readonly"; break;
case 4: temp = L"System"; break;
case 256: temp = L"Temporary"; break;
default: temp = L"Error or unsupported attribute"; break;
}
_tprintf(temp);
getch();
return 0;
}
what's wrong with this code? I always get 32 in d, even when I launch it with no attributes?
I'm using visual studio 2010.
Thank you!
argv[0] is the name of your executable program. Simply set the index to 1 (ensure it exists). You may also want to use a bitwise AND operation to determine if a flag is set.

convert string to argv in c++

I have an std::string containing a command to be executed with execv, what is the best "C++" way to convert it to the "char *argv[]" that is required by the second parameter of execv()?
To clarify:
std::string cmd = "mycommand arg1 arg2";
char *cmd_argv[];
StrToArgv(cmd, cmd_argv); // how do I write this function?
execv(cmd_argv[0], cmd_argv);
Very non-unixy answers here. What's wrong with:
std::string cmd = "echo hello world";
execl("/bin/sh", "/bin/sh", "-c", cmd.c_str(), NULL);
Why bother writing a command line parser when there's a perfectly good one already on the system?
(Note: one good reason is because you don't trust the string you're about to execute. One hopes that this is already true, but the shell will do "more" with that string than a naive whitespace-splitter will and thus open more security holes if you aren't careful.)
std::vector<char *> args;
std::istringstream iss(cmd);
std::string token;
while(iss >> token) {
char *arg = new char[token.size() + 1];
copy(token.begin(), token.end(), arg);
arg[token.size()] = '\0';
args.push_back(arg);
}
args.push_back(0);
// now exec with &args[0], and then:
for(size_t i = 0; i < args.size(); i++)
delete[] args[i];
Of course, this won't work with commans that use quoting like rm "a file.mp3". You can consider the POSIX function wordexp which cares about that and much more.
Perhaps split_winmain from Boost.ProgramOptions. Boost is a good choice in most cases.
http://www.boost.org/doc/libs/1_40_0/doc/html/program_options/howto.html#id1396212
If you are only interested in Windows (other kernels generally don't know about command lines in the Windows sense), you can use the API function CommandLineToArgvW which uses the same conventions as the MS C runtime.
In general it depends on the quoting style of the platform and/or the shell. The Microsoft C Runtime uses a quite different style than e.g. bash!
A combination of the c_str() string method and strtok() to split it up by spaces should get you the array of strings you need to pass to exec() and its related functions.
OK, I've been stumbling over this myself enough times. This is straight "C", so it can be plugged into either C or C++. It treats single and double quote strings differently. The caller is responsible for deallocating argv[0] (if not NULL) and argv.
#include
#include
#include
#include
typedef enum {
STR2AV_OK = 0,
STR2AV_UNBALANCED_QUOTE
} str_to_argv_err_t;
#ifndef NUL
#define NUL '\0'
#endif
static char const nomem[] = "no memory for %d byte allocation\n";
static str_to_argv_err_t
copy_raw_string(char ** dest_p, char ** src_p);
static str_to_argv_err_t
copy_cooked_string(char ** dest_p, char ** src_p);
static inline void *
Xmalloc(size_t sz)
{
void * res = malloc(sz);
if (res == NULL) {
fprintf(stderr, nomem, sz);
exit(EXIT_FAILURE);
}
return res;
}
static inline void *
Xrealloc(void * ptr, size_t sz)
{
void * res = realloc(ptr, sz);
if (res == NULL) {
fprintf(stderr, nomem, sz);
exit(EXIT_FAILURE);
}
return res;
}
str_to_argv_err_t
string_to_argv(char const * str, int * argc_p, char *** argv_p)
{
int argc = 0;
int act = 10;
char ** res = Xmalloc(sizeof(char *) * 10);
char ** argv = res;
char * scan;
char * dest;
str_to_argv_err_t err;
while (isspace((unsigned char)*str)) str++;
str = scan = strdup(str);
for (;;) {
while (isspace((unsigned char)*scan)) scan++;
if (*scan == NUL)
break;
if (++argc >= act) {
act += act / 2;
res = Xrealloc(res, act * sizeof(char *));
argv = res + (argc - 1);
}
*(argv++) = dest = scan;
for (;;) {
char ch = *(scan++);
switch (ch) {
case NUL:
goto done;
case '\\':
if ( (*(dest++) = *(scan++)) == NUL)
goto done;
break;
case '\'':
err = copy_raw_string(&dest, &scan);
if (err != STR2AV_OK)
goto error_leave;
break;
case '"':
err = copy_cooked_string(&dest, &scan);
if (err != STR2AV_OK)
goto error_leave;
break;
case ' ':
case '\t':
case '\n':
case '\f':
case '\r':
case '\v':
case '\b':
goto token_done;
default:
*(dest++) = ch;
}
}
token_done:
*dest = NUL;
}
done:
*argv_p = res;
*argc_p = argc;
*argv = NULL;
if (argc == 0)
free((void *)str);
return STR2AV_OK;
error_leave:
free(res);
free((void *)str);
return err;
}
static str_to_argv_err_t
copy_raw_string(char ** dest_p, char ** src_p)
{
for (;;) {
char ch = *((*src_p)++);
switch (ch) {
case NUL: return STR2AV_UNBALANCED_QUOTE;
case '\'':
*(*dest_p) = NUL;
return STR2AV_OK;
case '\\':
ch = *((*src_p)++);
switch (ch) {
case NUL:
return STR2AV_UNBALANCED_QUOTE;
default:
/*
* unknown/invalid escape. Copy escape character.
*/
*((*dest_p)++) = '\\';
break;
case '\\':
case '\'':
break;
}
/* FALLTHROUGH */
default:
*((*dest_p)++) = ch;
break;
}
}
}
static char
escape_convt(char ** src_p)
{
char ch = *((*src_p)++);
/*
* Escape character is always eaten. The next character is sometimes
* treated specially.
*/
switch (ch) {
case 'a': ch = '\a'; break;
case 'b': ch = '\b'; break;
case 't': ch = '\t'; break;
case 'n': ch = '\n'; break;
case 'v': ch = '\v'; break;
case 'f': ch = '\f'; break;
case 'r': ch = '\r'; break;
}
return ch;
}
static str_to_argv_err_t
copy_cooked_string(char ** dest_p, char ** src_p)
{
for (;;) {
char ch = *((*src_p)++);
switch (ch) {
case NUL: return STR2AV_UNBALANCED_QUOTE;
case '"':
*(*dest_p) = NUL;
return STR2AV_OK;
case '\\':
ch = escape_convt(src_p);
if (ch == NUL)
return STR2AV_UNBALANCED_QUOTE;
/* FALLTHROUGH */
default:
*((*dest_p)++) = ch;
break;
}
}
}
This is a variation on litb's answer, but without all the manual memory allocation. It still won't handle quoting.
#include <vector>
#include <string>
#include <sstream>
std::string cmd = "mycommand arg1 arg2";
std::istringstream ss(cmd);
std::string arg;
std::list<std::string> ls;
std::vector<char*> v;
while (ss >> arg)
{
ls.push_back(arg);
v.push_back(const_cast<char*>(ls.back().c_str()));
}
v.push_back(0); // need terminating null pointer
execv(v[0], &v[0]);
I feel kind of dirty about the const_cast<>, but programs really shouldn't be modifying the contents of the argv strings.
You can use the c_str() function of std::string to convert to char*.
The strtok function will split the string using the ' ' delimiter.
Matt Peitrek's LIBTINYC has a module called argcargv.cpp that takes a string and parses it out to the argument array taking quoted arguments into account. Note that it's Windows-specific, but it's pretty simple so should be easy to move to whatever platform you want.
If you do that, also change it to take as parameters the loaction to put the count and the a pointer to the argv array instead of using externs (just my little bit of advice). Matt didn't need that because LIBTINYC was the runtime.
Alternatively, you can look in your compiler's runtime source (nearly all provide it) to see what they do to parse the commandline and either call that directly (if that turns out to be workable) or borrow the ideas from that bit of code.
May be it is too late to answer on this question but you could use standart POSIX functions glob or wordexp:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <wordexp.h>
int
main(int argc, char **argv)
{
wordexp_t p;
char *exec_path = "/bin/ls";
p.we_offs = 1;
wordexp("-l -t /etc", &p, WRDE_DOOFFS);
p.we_wordv[ 0 ] = exec_path;
execv(exec_path, p.we_wordv);
/* This code is unreachable */
exit(EXIT_SUCCESS);
}
It would prepare 3 parameters: -l (long listing format), -t (sort by modification time) and directory /etc to list, and run /bin/ls. Call wordexp() gives you exactly the same result as call /bin/sh -c recomended previously but spawaned process would have parent process not /bin/sh.
As it turned out a function exist somewhat hidden in boost program options for this.
The split_unix() function works with escaped and quoted command lines.
#include "boost/program_options/parsers.hpp"
auto parts = boost::program_options::split_unix(commandLine);
std::vector<char*> cstrings ;
for(auto& str : parts){
cstrings.push_back(const_cast<char*> (str.c_str()));
}
int argc = (int)cstrings.size();
char** argv = cstrings.data();