I'm having trouble identifying a possible source of memory corruption in the following code. Is it due to the fact that I don't call the free() function on char *stringToAdd?
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <cstring>
#include <iostream>
using namespace std;
#define MAX 1024
char* add_strings(char *stringOne, char *stringTwo);
int main() {
char s = 'x';
char *stringOne = &s;
char *stringTwo = new char[1025]();
char *final = add_strings(stringOne, stringTwo);
return 0;
}
char* add_strings(char *stringOne, char *stringTwo) {
unsigned int lengthOfStringOne = strlen(stringOne);
unsigned int lengthOfStringTwo = strlen(stringTwo);
cout << lengthOfStringOne << endl;
cout << lengthOfStringTwo << endl;
char *stringToAdd = lengthOfStringOne < lengthOfStringTwo ? stringOne : stringTwo;
unsigned int lengthOfAdd = lengthOfStringOne < lengthOfStringTwo ? lengthOfStringOne : lengthOfStringTwo;
char *final = static_cast<char*>(calloc(MAX, sizeof(char)));
unsigned int avgLengthOfStrings = (lengthOfStringOne + lengthOfStringTwo) / 2;
if (avgLengthOfStrings < MAX) {
strncat(final, stringToAdd, lengthOfAdd);
printf("DONE\n");
} else {
printf("Average length of both input strings exceeds liimit.\n");
free(final);
return NULL;
}
return final;
}
Related
How can I convert it? And I want the converted result to 1.
#include <iostream>
#include <string>
int main(int argc, const char * argv[]) {
std::string s = "0x00";
// insert code here...
unsigned char* str_hex = (unsigned char*)s.c_str();
unsigned char target = 0x00;
std::cout << "result: " << (*str_hex == target) << "\n";
return 0;
}
Like this: // #include <string>
std::string s = "0x4A";
unsigned char ch = std::stoul(s, nullptr, 16); // 'J' (Since C++11)
Or like this: // #include <cstdio>
std::string s = "0x4B";
unsigned char ch = '\0';
sscanf(s.c_str(), "%x", &ch); // 'K' (C library function)
I am having a problem in trying to serialize an array of unsigned char into file with GZIP compression using protobuf while playing with the library.
I think the problem might have to do with some of my syntax or misuse of API.
I have also tried std::fstream.
FYI, Windows 8.1 & VS2013 is the building environment.
scene.proto
syntax = "proto3";
package Recipe;
message Scene
{
repeated int32 imageData = 1 [packed=true];
}
source.cpp
#include <iostream>
#include <fstream>
#include <ostream>
#include <istream>
#include <string>
#include <cstdint>
#include "Scene.pb.h"
#include <google\protobuf\io\zero_copy_stream_impl.h>
#include <google\protobuf\io\gzip_stream.h>
int const _MIN = 0;
int const _MAX = 255;
unsigned int const _SIZE = 65200000;
unsigned int const _COMPRESSION_LEVEL = 10;
void randWithinUnsignedCharSize(uint8_t * buffer, unsigned int size)
{
for (size_t i = 0; i < size; ++i)
{
buffer[i] = _MIN + (rand() % static_cast<int>(_MAX - _MIN + 1));
}
}
using namespace google::protobuf::io;
int main()
{
GOOGLE_PROTOBUF_VERIFY_VERSION;
Recipe::Scene * scene = new Recipe::Scene();
uint8_t * imageData = new uint8_t[_SIZE];
randWithinUnsignedCharSize(imageData, _SIZE);
for (size_t i = 0; i < _SIZE; i++)
{
scene->add_imagedata(imageData[i]);
}
std::cout << "scene->imagedata_size() " << scene->imagedata_size() << std::endl;
{
std::ofstream output("scene.art", std::ofstream::out | std::ofstream::trunc | std::ofstream::binary);
OstreamOutputStream outputFileStream(&output);
GzipOutputStream::Options options;
options.format = GzipOutputStream::GZIP;
options.compression_level = _COMPRESSION_LEVEL;
GzipOutputStream gzipOutputStream(&outputFileStream, options);
if (!scene->SerializeToZeroCopyStream(&gzipOutputStream)) {
std::cerr << "Failed to write scene." << std::endl;
return -1;
}
}
Recipe::Scene * scene1 = new Recipe::Scene();
{
std::ifstream input("scene.art", std::ifstream::in | std::ifstream::binary);
IstreamInputStream inputFileStream(&input);
GzipInputStream gzipInputStream(&inputFileStream);
if (!scene1->ParseFromZeroCopyStream(&gzipInputStream)) {
std::cerr << "Failed to parse scene." << std::endl;
return -1;
}
}
std::cout << "scene1->imagedata_size() " << scene1->imagedata_size() <<std::endl;
google::protobuf::ShutdownProtobufLibrary();
return 0;
}
You seem to have a typo in your code. Compression level is according to documentation in range 0-9. You set incorrectly compression level to 10.
Your example is working for me when corrected to:
unsigned int const _COMPRESSION_LEVEL = 9;
#include <iostream>
#include <fstream>
#include <string.h>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <semaphore.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#include <vector>
#include <sstream>
#define SHMSIZE 1024
using namespace std;
namespace patch
{
template < typename T > std::string to_string( const T& n )
{
std::ostringstream stm ;
stm << n ;
return stm.str() ;
}
}
struct process
{
int r;
string name;
vector<string> lines;
};
int main(int argc, char * argv[])
{
int firstRun = 1; //Skipping First Line of Assign-1.ip.
int quantum = 0; //For taking input of quantum.
int count = 0; //For number of processes.
int pchtoint;
string c;
char * pch; //For tokenization.
string reading_file; //Reading a line from file.
char * readarr; //Converting "reading_file" to readarr for tokenization.
process * p;
//=== Quantum Input ===//
cout<<"Enter Quantum size [1-1000]: ";
cin>>quantum;
while(quantum < 1 || quantum > 1000)
{
cout<<"Wrong input!!! Enter Again [1-1000]: ";
cin>>quantum;
}
//=====================//
//===Filing===//
ifstream read("Assign-2.ip");
if(read.is_open())
{
while(!read.eof())
{
getline(read, reading_file);
readarr = new char[reading_file.size() + 1];
for(int i = 0; i < reading_file.length(); i++)
{
readarr[i] = reading_file[i];
}
if(firstRun > 1)
{
int countingline = 0; //counting the number of lines in a process.
pch = strtok (readarr," ,");
while (pch != NULL)
{
c = pch[1];
pchtoint = atoi(c.c_str());
p[pchtoint-1].r++;
p[pchtoint-1].lines.push_back(pch);
for(int i = 0; i < p[pchtoint-1].lines.size(); i++)
cout<<p[pchtoint-1].name<<"=="<<p[pchtoint-1].lines.at(i)<<endl;
pch = strtok (NULL, " ,");
}
}
else
{
pch = strtok (readarr,",.-");
while (pch != NULL)
{
count++;
pch = strtok (NULL, ",.-");
}
p = new process[count];
string s = "p";
for(int i = 0; i < count; i++)
{
s = s + patch::to_string(i+1);
p[i].name = s;
s = s[0];
}
firstRun++;
}
}
}
else
{
cout<<"Cannot open file!!!"<<endl;
}
read.close();
return 0;
}
Enter Quantum size [1-1000]: 2
p1==p1-l1
p2==p2-l1
p3==p3-l1
p1==p1-l1
p1==p1-l2
p2==p2-l1
p2==p2-l2
p3==p3-l1
p3==p3-l2
p1==p1-l1
p1==p1-l2
p1==p1-l3
p3==p3-l1
p3==p3-l2
p3==p3-l3
p1==p1-l1
p1==p1-l2
p1==p1-l3
p1==p1-l4
Segmentation fault (core dumped)
I am reading data from a cvs file. and storing it in struct that is p here. but I don't know why it is giving segmentation fault. I am compiling it on ubuntu terminal.
The input file contains data:
P1, P2, P3,
p1-l1, p2-l1, p3-l1
p1-l2, p2-l2, p3-l2
p1-l3, , p3-l3
p1-l4, ,
What's the correct way to add a character array to a constant character array in C++?
#include <iostream>
using namespace std;
int main(int argc, char** argv) {
int pathSize = 0;
char* pathEnd = &argv[0][0];
while(argv[0][pathSize] != '\0') {
if(argv[0][pathSize++] == '/')
pathEnd = &argv[0][0] + pathSize;
}
pathSize = pathEnd - &argv[0][0];
char *path = new char[pathSize];
for(int i = 0; i < pathSize; i++)
path[i] = argv[0][i];
cout << "Documents Path: " << path + "docs/" << endl; // Line Of Interest
delete[] path;
return 0;
}
This code outputs:
Documents Path: �\
Using 'path' instead of '*path' will give me the compile error:
invalid operands of types ‘char*’ and ‘const char [6]’ to binary ‘operator+’
May I suggest using C++ to begin with, and (Boost) Filesystem for maximum benefits:
#include <iostream>
#include <boost/filesystem.hpp>
using namespace std;
using namespace boost::filesystem;
int main(int argc, const char *argv[])
{
const std::vector<std::string> args { argv, argv+argc };
path program(args.front());
program = canonical(program);
std::cout << (program.parent_path() / "docs").native();
}
This will use the platform's path separator, know how to translate 'funny' paths (e.g. containing ..\..\, or UNC paths).
Something like this should do it (totally untested):
const char* end = strrchr(argv[0], '/');
std::string docpath = end ? std::string(argv[0], end) : std::string(".");
docpath += '/docs/';
Your way:
#include <iostream>
using namespace std;
int main(int argc, char** argv) {
int pathSize = 0;
char* pathEnd = &argv[0][0];
while(argv[0][pathSize] != '\0') {
if(argv[0][pathSize++] == '/')
pathEnd = &argv[0][0] + pathSize;
}
pathSize = pathEnd - &argv[0][0];
char *path = new char[pathSize + 5]; //make room for "docs/"
for(int i = 0; i < pathSize; i++)
path[i] = argv[0][i];
char append[] = "docs/";
for(int i = 0; i < 5; i++)
path[pathSize+i] = append[i];
cout << "Documents Path: " << path << endl;
function_expecting_charptr(path);
delete[] path;
return 0;
}
Sane C way:
#include <iostream>
using namespace std;
int main(int argc, char** argv) {
char* pathEnd = strrchr(argv[0], '/');
if (pathEnd == NULL)
pathEnd = argv[0];
int pathSize = (pathEnd-argv[0]) + 5; //room for "docs/"
char *path = new char[pathSize];
if (pathSize)
strncpy(path, argv[0], pathSize+1);
strcat(path, "docs/");
cout << "Documents Path: " << path << endl;
function_expecting_charptr(path);
delete[] path;
return 0;
}
C++ way:
#include <iostream>
#include <string>
int main(int argc, char** argv) {
std::string path = argv[0];
size_t sep = path.find('/');
if (sep != std::string::npos)
path.erase(sep+1);
else
path.clear();
path += "docs/";
std::cout << "Documents Path: " << path << endl;
function_expecting_charptr(path.c_str());
return 0;
}
Note that argv[0] holds an implementation defined value, and especially in *nix environments isn't guaranteed to hold anything useful. The first parameter passed to the program is found in argv[1].
I combined some of your guys' ideas into this compact code:
#include <iostream>
#include <cstring>
using namespace std;
int main(int argc, char** argv) {
const string path_this = argv[0];
const string path = path_this.substr(0, strrchr(argv[0], '/') - argv[0] +1);
const string path_docs = path + "docs/";
cout << "Documents Path: " << path_docs << endl;
return 0;
}
To get the character array from this I can then run 'path_docs.c_str()'.
Credits: #MooingDuck, #MarkB, Google.
#include <iostream>
#include <string.h> // for strlen
#include <stdlib.h> // for atoi
#include <sstream>
void expand_combinations(const char *remaining_string, std::ostringstream& i, int remain_depth)
{
if(remain_depth==0)
{
std::cout << i.str() << std::endl;
return;
}
for(int k=0; k < strlen(remaining_string); ++k)
{
std::ostringstream l;
l << i.str();
l << remaining_string[k];
expand_combinations(remaining_string+k+1, l, remain_depth - 1);
}
return;
}
int main(int argc, char **argv)
{
std::ostringstream i;
if(argc<3) return 1;
expand_combinations(argv[1], i, atoi(argv[2]));
return 0;
}
How can this code be changed so that it doesn't use ostringstream?
The following is your code with string in place of ostringstream. Normally I'd refactor the code but since your question was pretty specific I'll leave it alone.
#include <iostream>
#include <string>
#include <stdlib.h>
using namespace std;
void expand_combinations(const char *remaining_string, string const & s, int remain_depth)
{
if(remain_depth==0)
{
std::cout << s << std::endl;
return;
}
for(int k=0; k < strlen(remaining_string); ++k)
{
string str(s);
str.append(1, remaining_string[k]);
expand_combinations(remaining_string+k+1, str, remain_depth - 1);
}
return;
}
int main(int argc, char **argv)
{
if(argc<3) return 1;
expand_combinations(argv[1], "", atoi(argv[2]));
return 0;
}