I have read other threads on pset5 Valgrind memory errors, but that didn't help me. I get 0 leaks, but this instead:
==1917== Conditional jump or move depends on uninitialised value(s)
Looks like you're trying to use a variable that might not have a value? Take a closer look at line 34 of dictionary.c.
The error refers to line 34 which is this: lower[i] = tolower(word[i]);
To supply context, the code below attempts to check if a word exists in the dictionary that has been uploaded to a hash table. I am attempting to convert the wanted word to lowercase because all the dictionary words are also lowercase and so that their hashes would be identical. The program successfully completes all tasks, but then stumbles upon these memory errors.
Any hints as to why Valgrind is mad at me? Thank you!
// Returns true if word is in dictionary else false
bool check(const char *word)
{
char lower[LENGTH + 1];
//Converts word to lower so the hashes of the dictionary entry and searched word would match
for (int i = 0; i < LENGTH + 1; i++)
{
lower[i] = tolower(word[i]);
}
// Creates node from the given bucket
node *tmp = table[hash(lower)];
// Traverses the linked list
while (tmp != NULL)
{
if (strcasecmp(word, tmp->word) == 0)
{
return true;
}
tmp = tmp->next;
}
return false;
}
Below is the whole dictionary.c file:
// Implements a dictionary's functionality
#include <string.h>
#include <strings.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "dictionary.h"
// Represents a node in a hash table
typedef struct node
{
char word[LENGTH + 1];
struct node *next;
}
node;
// Number of buckets in hash table 26^3
const unsigned int N = 17576;
// Hash table
node *table[N];
int count = 0;
// Returns true if word is in dictionary else false
bool check(const char *word)
{
char lower[LENGTH + 1];
//Converts word to lower so the hashes of the dictionary entry and searched word would match
for (int i = 0; i < LENGTH + 1; i++)
{
lower[i] = tolower(word[i]);
}
// Creates node from the given bucket
node *tmp = table[hash(lower)];
// Traverses the linked list
while (tmp != NULL)
{
if (strcasecmp(word, tmp->word) == 0)
{
return true;
}
tmp = tmp->next;
}
return false;
}
// Hashes word to a number
unsigned int hash(const char *word)
{
// Modified hash function by Dan Berstein taken from http://www.cse.yorku.ca/~oz/hash.html
unsigned int hash = 5381;
int c;
while ((c = *word++))
{
hash = (((hash << 5) + hash) + c) % N; /* hash * 33 + c */
}
return hash;
}
// Loads dictionary into memory, returning true if successful else false
bool load(const char *dictionary)
{
FILE *inptr = fopen(dictionary, "r");
if (dictionary == NULL)
{
printf("Could not load %s\n.", dictionary);
return false;
}
// Create a char array to temporarily hold the new word (r stands for read)
char r_word[N+1];
// Until the end of file
while (fscanf(inptr, "%s", r_word) != EOF)
{
// Increments count
count++;
// Create a node
node *new_node = malloc(sizeof(node));
if (new_node == NULL)
{
unload();
return false;
}
strcpy(new_node->word, r_word);
// Hash the node
int index = hash(new_node->word);
// Places the node at the right index
new_node->next = table[index];
table[index] = new_node;
}
fclose(inptr);
return true;
}
// Returns number of words in dictionary if loaded else 0 if not yet loaded
unsigned int size(void)
{
if (&load == false)
{
return '0';
}
else
{
return count;
}
}
// Unloads dictionary from memory, returning true if successful else false
bool unload(void)
{
// Interates over the array
for (int i = 0; i < N; i++)
{
node *head = table[i];
while (head != NULL)
{
node *tmp = head;
head = head->next;
free(tmp);
}
}
return true;
}
This loop iterates through the maximum length of word-
for (int i = 0; i < LENGTH + 1; i++)
{
lower[i] = tolower(word[i]);
}
Except if you look at how word is created-
while (fscanf(inptr, "%s", r_word) != EOF)
{
// Increments count
count++;
// Create a node
node *new_node = malloc(sizeof(node));
if (new_node == NULL)
{
unload();
return false;
}
strcpy(new_node->word, r_word);
Notice, the variable r_word, may not be exactly of length LENGTH + 1. So what you really have in word is N number of characters, where N is not necessarily LENGTH + 1, it could be less.
So looping over the entire 0 -> LENGTH + 1 becomes problematic for words that are shorter than LENGTH + 1. You're going over array slots that do not have a value, they have garbage values.
What's the solution? This is precisely why c strings have \0-
for (int i = 0; word[i] != '\0'; i++)
{
lower[i] = tolower(word[i]);
}
This will stop the loop as soon as the NULL character is reached, which, you must have already learnt, marks the end of a string - aka a char array.
There may still be more errors in your code. But for your particular question - reading out of bounds is the answer.
EDIT:
Here's the complete code. modified the code to work with a router but the use case is same. Once i issue the password using libssh2_channel_write() subsequent libssh2_channel_read() fails with LIBSSH2_ERROR_SOCKET_RECV. Not sure why. I am unable to send subsequent commands to the remote device and get their output.
Logic was to execute a command on the remote device ( libssh2_channel_exec ). This command execution would throw a password to be entered by the client. Now read the stream via libssh2_channel_read() and ensure that the password is being asked and write the password to the channel via libssh2_channel_write(). Ensure the password is accepted on the remote device by doing subsequent reads [ THIS IS WHERE THE LIB IS FAILING WITH ERROR_SOCKET_RECV ] and then send the command to be executed via libssh2_channel_write() and read the command output. Am i missing something ?
for( ;; )
{
/* loop until we block */
int rc;
do
{
char buffer[0x4000];
rc = libssh2_channel_read( channel, buffer, sizeof(buffer) );
if( rc > 0 )
{
int i;
char *enable = "check-password\n";
int ret;
bytecount += rc;
fprintf(stderr, "We read [%d] bytes:\n", bytecount);
fputc('[', stderr);
for( i=0; i < rc; ++i )
fputc( buffer[i], stderr);
fputc(']', stderr);
if ( strstr(buffer, "Password:") != NULL ){
fprintf(stderr, "Sending the password now\n");
while((ret = libssh2_channel_write(channel, enable, strlen(enable))) == LIBSSH2_ERROR_EAGAIN) {
printf("ERROR_EAGAIN - sending password again\n");
}
fprintf(stderr, "Wrote [%d] bytes: \n", ret);
flag = 1;
continue;
}
if (!flag){ // start
char *cmd = "show clock\n";
int ret;
fprintf(stderr, "THIS Fetching show clock command now\n");
while((ret = libssh2_channel_write(channel, cmd, strlen(cmd))) == LIBSSH2_ERROR_EAGAIN) {
printf("ERROR_EAGAIN - sending show clock again\n");
}
flag = 1;
} // end
}
else {
if(rc != LIBSSH2_ERROR_EAGAIN)
fprintf(stderr, "libssh2_channel_read returned [%d]:\n ", rc);
}
}
while( rc > 0 );
/* this is due to blocking that would occur otherwise so we loop on
this condition */
if( rc == LIBSSH2_ERROR_EAGAIN )
{
int check;
check = waitsocket(sock, session);
}
else
break;
}
I am trying to write a program that will take an integer input, and then convert it to words. for example: 123, one two three. Also -3908, negative three nine zero eight.
My code works 90% of the time, the only issue coming along when i am putting one or more zeros on the end of the integer. eg. 70800 will come up as seven zero eight. It completely misses the end zeros. I understand why that is happening but does anybody know if there is a way around it.
PS(i am not allowed as a part of this task to accept the input as a string and split it into an array, so it would be best if the answer is based off this code).
int main(int argc, const char * argv[])
{
#autoreleasepool {
float abNumber;
int i = 0;
float number;
float result;
float firstNumber;
printf("type a number: ");
scanf("%f", &firstNumber);
abNumber = abs(firstNumber);
if (firstNumber < 0) {
printf("negative ");
}
number = abNumber;
while (number >= 10) {
number = number / 10;
i++;
}
do {
float countNumber = abNumber;
float power = powf(10, -i);
float powerNo2 = powf(10, i);
countNumber = countNumber * power;
result = floorf(countNumber);
if (result == 9){
printf("nine ");
}
if (result == 8){
printf("eight ");
}
if (result == 7){
printf("seven ");
}
if (result == 6){
printf("six ");
}
if (result == 5){
printf("five ");
}
if (result == 4){
printf("four ");
}
if (result == 3){
printf("three ");
}
if (result == 2){
printf("two ");
}
if (result == 1){
printf("one ");
}
if (result == 0){
printf("zero ");
}
while (abNumber > powerNo2) {
abNumber = abNumber - powerNo2;
}
i--;
} while (i >= 0);
}
return 0;
}
The main error seems to be that
while (abNumber > powerNo2) {
should be
while (abNumber >= powerNo2) {
But I would recommend not to use floating point arithmetic at all, to avoid
possible rounding errors. The same can be achieved with simple integer arithmetic
(I have omitted the "negative case" for simplicity):
int number;
printf("type a number: ");
scanf("%d", &number);
// Determine highest power of 10 that is <= the given number:
int power = 1;
while (10 * power <= number) {
power *= 10;
}
// Extract each digit:
while (power > 0) {
int digit = (number / power) % 10;
/*
* Use switch/case to print 'digit' as a string ...
*/
power /= 10;
}
I would go for recursive solution, like that
int print(int num)
{
if( num )
{
int mod = num%10;
print(num/10);
switch(mod)
{
case 0:printf(" zero");break;
case 1:printf(" one");break;
case 2:printf(" two");break;
case 3:printf(" three");break;
}
}
return 0;
}
Recursivy divide the number untill nothing left of it, on the way back print the mod.
Why don't you just input the number as a string then loop through each character:
Exemple: http://ideone.com/E8QspN
Input:
-12003200
Output:
negative one two zero zero tree two zero zero
Code:
#include <stdio.h>
int main(int argc, char *argv[])
{
char input[25];
scanf("%s", input);
int i = 0;
while (input[i] != '\0') {
switch(input[i]) {
case '-' :
printf("negative");
break;
case '0' :
printf("zero");
break;
case '1' :
printf("one");
break;
case '2' :
printf("two");
break;
case '3' :
printf("tree");
break;
case '4' :
printf("four");
break;
case '5' :
printf("five");
break;
case '6' :
printf("six");
break;
case '7' :
printf("seven");
break;
case '8' :
printf("eight");
break;
case '9' :
printf("nine");
break;
default :
break;
}
printf(" ");
i++;
}
return 0;
}
Consider the following:
Code
#include <stdio.h>
#include <stdlib.h>
const char *numbers[10] = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};
void printNum(int num);
int main(void)
{
int num;
printf("Enter a number: ");
scanf("%u", &num);
printNum(num);
printf("\n");
return 0;
}
void printNum(int num)
{
int absNum = abs(num);
if(absNum > 9)
printNum(num / 10);
if((absNum < 10) && (num < 0))
printf("negative");
printf(" %s", numbers[absNum % 10]);
}
Example Output
Enter a number: 2582
two five eight two
Enter a number: -943
negative nine four three
Enter a number: 1000
one zero zero zero
Enter a number: -1000
negative one zero zero zero
Logic
Get an integer from user.
Send to recursive function.
Keep recursing until the least significant digit is left. This is to print in the correct order.
Print digit as a string by using a lookup table.
Keep someone a high five.
To Do
Error checking
I just cann't seem to get the FFMpeg working with using the library. Everytime I try to convert asf file to wmv. I get the following issue on run time:
[wmv1 # 0x81ee000]error, slice code was 2
[wmv1 # 0x81ee000]header damaged
This my code:
static void audio_decode_example(const char *outfilename, const char *filename)
{
AVCodec *codec;
AVCodecContext *c= NULL;
int out_size, len, in_size;
FILE *f, *outfile;
uint8_t *outbuf;
uint8_t inbuf[AUDIO_INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
AVPacket avpkt;
av_init_packet(&avpkt);
printf("Audio decoding\n");
/* find the mpeg audio decoder */
codec = avcodec_find_decoder(CODEC_ID_WMV1);
if (!codec) {
fprintf(stderr, "codec not found\n");
return;
}
c= avcodec_alloc_context2(CODEC_TYPE_AUDIO);
/* open it */
if (avcodec_open(c, codec) < 0) {
fprintf(stderr, "could not open codec\n");
return;
}
outbuf = malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
f = fopen(filename, "rb");
if (!f) {
fprintf(stderr, "could not open %s\n", filename);
return;
}
outfile = fopen(outfilename, "wb");
if (!outfile) {
av_free(c);
return;
}
/* decode until eof */
avpkt.data = inbuf;
len = avpkt.size = fread(inbuf, 1, INBUF_SIZE, f);
NSLog(#"%d", avpkt.size);
while (avpkt.size > 0) {
out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
len = avcodec_decode_audio2(c, (short *)outbuf, &out_size, inbuf,len);// avpkt.size);
NSLog(#"%d", len);
if (len < 0) {
fprintf(stderr, "Error while decoding\n");
fclose(outfile);
return;
}
if (out_size > 0) {
/* if a frame has been decoded, output it */
fwrite(outbuf, 1, out_size, outfile);
}
avpkt.size -= len;
avpkt.data += len;
if (avpkt.size < AUDIO_REFILL_THRESH) {
/* Refill the input buffer, to avoid trying to decode
* incomplete frames. Instead of this, one could also use
* a parser, or use a proper container format through
* libavformat. */
memmove(inbuf, avpkt.data, avpkt.size);
avpkt.data = inbuf;
len = fread(avpkt.data + avpkt.size, 1,
INBUF_SIZE - avpkt.size, f);
if (len > 0)
avpkt.size += len;
}
}
fclose(outfile);
fclose(f);
free(outbuf);
avcodec_close(c);
av_free(c);
}
I have try the command line utilities and it successfully convert the file. Any help would be helpfully. thanks
Make the mistake of opening the wrong file
I have read around 50 posts and tutorials on this topic, I have copied, written and tested around 20 alternatives and done every possible research I can think of. Still, I have not seen a working solution for the following problem:
Parent process A wants to pass data to an external process B, let process B modify the data and pass it back to parent process A, then continue with parent process A. Process B is part of an external program suite that I have no influence over, and that is normally run like this on the UNIX command line:
< input_data program_B1 | program_B2 | program_B3 > output_data
...where
input_data, output_data: Some data that is processed in programs B1-B3
program_B1,B2,B3: Programs that read data from stdin (fread) and output to stdout (fwrite) and apply some processing to the data.
So, in sequence:
(1) Parent process A passes data to child process B
(2) Child process B reads data and modifies it
(3) Child process B passes data back to parent process A
(4) Parent process A reads data and continues (for example passing it further on to a process B2..).
(5) Parent process A passes another data set to child process B etc.
The problem is, whatever I do, the program almost always ends up hanging on a read/fread (or write/fwrite?) to or from a pipe.
One important thing to note is that the parent process cannot simply close the pipes after passing data on to the child process, because it works in a loop and wants to pass another set of data to the child process once it has finished processing the first set.
Here is a working set of parent/child programs (compile with g++ pipe_parent.cc -o pipe_parent, g++ pipe_child.cc -o pipe_child) illustrating the problem with unnamed pipes. I have also tried named pipes, but not as extensively. Each execution can have a slightly different outcome. If the sleep statement is omitted in the parent, or the fflush() statement is omitted in the child, the pipes will almost surely block. If the amount of data to be passed on is increased, it will always block independent of the sleep or fflush.
Parent program A:
#include <cstring>
#include <cstdio>
#include <cstdlib>
extern "C" {
#include <unistd.h>
#include <fcntl.h>
}
using namespace std;
/*
* Parent-child inter-communication
* Child is external process
*/
int main() {
int fd[2];
if( pipe(fd) == -1 ) {
fprintf(stderr,"Unable to create pipe\n");
}
int fd_parentWrite = fd[1];
int fd_childRead = fd[0];
if( pipe(fd) == -1 ) {
fprintf(stderr,"Unable to create pipe\n");
exit(-1);
}
int fd_childWrite = fd[1];
int fd_parentRead = fd[0];
pid_t pid = fork();
if( pid == -1 ) {
fprintf(stderr,"Unable to fork new process\n");
exit(-1);
}
if( pid == 0 ) { // Child process
dup2( fd_childRead, fileno(stdin) ); // Redirect standard input(0) to child 'read pipe'
dup2( fd_childWrite, fileno(stdout) ); // Redirect standard output(1) to child 'write pipe'
close(fd_parentRead);
close(fd_parentWrite);
close(fd_childRead);
close(fd_childWrite);
// execl replaces child process with an external one
int ret = execl("/disk/sources/pipe_test/pipe_child","pipe_child",NULL);
fprintf(stderr,"External process failed, return code: %d...\n", ret);
exit(-1);
// Child process is done. Will not continue from here on
}
else { // Parent process
// Nothing to set up
}
// ...more code...
if( pid > 0 ) { // Parent process (redundant if statement)
int numElements = 10000;
int totalSize = numElements * sizeof(float);
float* buffer = new float[numElements];
for( int i = 0; i < numElements; i++ ) {
buffer[i] = (float)i;
}
for( int iter = 0; iter < 5; iter++ ) {
fprintf(stderr,"--------- Iteration #%d -----------\n", iter);
int sizeWrite = (int)write( fd_parentWrite, buffer, totalSize );
if( sizeWrite == -1 ) {
fprintf(stderr,"Parent process write error\n");
exit(-1);
}
fprintf(stderr,"Parent #%d: Wrote %d elements. Total size: %d\n", iter, sizeWrite, totalSize);
sleep(1); // <--- CHANGE!
int sizeRead = (int)read( fd_parentRead, buffer, totalSize );
if( sizeRead <= 0 ) {
fprintf(stderr,"Parent process read error\n");
}
while( sizeRead < totalSize ) {
fprintf(stderr,"Parent #%d: Read %d elements, continue reading...\n", iter, sizeRead);
int sizeNew = (int)read( fd_parentRead, &buffer[sizeRead], totalSize-sizeRead );
fprintf(stderr," ...newly read %d elements\n", sizeNew);
if( sizeNew < 0 ) {
exit(-1);
}
sizeRead += sizeNew;
}
fprintf(stderr,"Parent #%d: Read %d elements. Total size: %d\n", iter, sizeRead, totalSize);
fprintf(stderr,"Examples : %f %f %f\n", buffer[0], buffer[10], buffer[100]);
}
delete [] buffer;
}
close(fd_parentRead);
close(fd_parentWrite);
close(fd_childRead);
close(fd_childWrite);
return 0;
}
Child program B:
#include <cstdio>
using namespace std;
int main() {
int numElements = 10000;
int totalSize = numElements * sizeof(float);
float* buffer = new float[numElements];
int counter = 0;
int sizeRead = 0;
do {
sizeRead = fread( buffer, 1, totalSize, stdin);
fprintf(stderr,"Child #%d: Read %d elements, buffer100: %f\n", counter, sizeRead, buffer[100]);
if( sizeRead > 0 ) {
for( int i = 0; i < numElements; i++ ) {
buffer[i] += numElements;
}
int sizeWrite = fwrite( buffer, 1, totalSize, stdout);
fflush(stdout); // <--- CHANGE!
fprintf(stderr,"Child #%d: Wrote %d elements\n", counter, sizeWrite);
counter += 1;
}
} while( sizeRead > 0 );
return 0;
}
Is there any way to check when the pipe has enough data to be read? Or is there an alternative way to resolve the above problem, with or without pipes?
Please help!
Possibly the best solution when reading is to check with select whether you can read from the pipe. You can even pass a timeout. The alternative might be setting the O_NONBLOCK flag on file descriptor 0 (stdin) with fcntl, though I think the select way is better.
As with ensuring non-blocking write: that's a bit harder as you don't know how much you can write before the pipe blocks. One way (that I feel is very ugly) would be to only write 1 byte chunks and again check with select whether you can write. But that would be a performance killer, so use only if performance in communication is not an issue.
The first answer (using select to find out whether a pipe is ready to be read from) was good but didn't really solve my issue, see also my previous comments. Sooner or later I always ended up with a "race condition" where the program kept hanging either on a read or write.
The solution (maybe not be the only one?) is to run the child-to-parent data transfer in a different thread. I also went back and implemented the pipes as named pipes. It would probably also work with unnamed pipes but I didn't check that.
The final code is below. Note that no explicit flushing is required; the parent-to-child and child-to-parent data transfers are now decoupled. Any comments how this can be improved welcome! One residual problem I can see is that the pipes may fill up depending on how long time the child needs to process the data. I'm not sure how likely this is to happen. And by the way this worked fine with my external programs, not only with the provided child program.
Parent program A:
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <iostream>
extern "C" {
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <signal.h>
#include <sys/wait.h>
#include <pthread.h>
}
using namespace std;
static int const READING = -1;
static int const BUFFER_READY = 1;
static int const FINISHED = 0;
/*
* Parent-child inter-communication
* Child is external process
*/
struct threadStruct {
FILE* file_c2p;
int sizeBuffer;
float* buffer;
int io_flag;
};
// Custom sleep function
void mini_sleep( int millisec ) {
struct timespec req={0},rem={0};
time_t sec = (int)(millisec/1000);
millisec = (int)(millisec-(sec*1000));
req.tv_sec = sec;
req.tv_nsec = millisec*1000000L;
nanosleep(&req,&rem);
}
// Function to be executed within separate thread: Reads in data from file pointer
// Hand-shaking with main thread is done via the flag 'io_flag'
void *threadFunction( void *arg ) {
threadStruct* ptr = (threadStruct*)arg;
ptr->io_flag = READING;
while( ptr->io_flag != FINISHED ) {
if( ptr->io_flag == READING ) {
int sizeRead = fread( ptr->buffer, 1, ptr->sizeBuffer, ptr->file_c2p );
if( sizeRead <= 0 ) {
ptr->io_flag = FINISHED;
return NULL;
}
ptr->io_flag = BUFFER_READY;
}
else {
mini_sleep(10);
}
}
return NULL;
}
//--------------------------------------------------
int main() {
std::string filename_p2c("/tmp/fifo11_p2c");
std::string filename_c2p("/tmp/fifo11_c2p");
fprintf(stderr,"..started\n");
int status = mknod(filename_p2c.c_str(), S_IRUSR | S_IWUSR | S_IFIFO, 0);
if( (status == -1) && (errno != EEXIST) ) {
fprintf(stderr,"Error creating named pipe: %s\n", strerror(errno));
exit(-1);
}
status = mknod(filename_c2p.c_str(), S_IRUSR | S_IWUSR | S_IFIFO, 0);
if( (status == -1) && (errno != EEXIST) ) {
fprintf(stderr,"Error creating named pipe: %s\n", strerror(errno));
exit(-1);
}
FILE* file_dump = fopen("parent_dump","w");
int fd_p2c;
int fd_c2p;
FILE* file_c2p = NULL;
//--------------------------------------------------
// Set up parent/child processes
//
pid_t pid = fork();
if( pid == -1 ) {
fprintf(stderr,"Unable to fork new process\n");
}
if( pid == 0 ) { // Child process
fd_p2c = open( filename_p2c.c_str(), O_RDONLY );
if( fd_p2c < 0 ) {
fprintf(stderr,"Child: Error opening the named pipe: %d %d '%s'\n", fd_p2c, errno, strerror(errno));
exit(-1);
}
fd_c2p = open( filename_c2p.c_str(), O_WRONLY );
if( fd_c2p < 0 ) {
fprintf(stderr,"Child: Error opening the named pipe: %d %d '%s'\n", fd_c2p, errno, strerror(errno));
exit(-1);
}
dup2(fd_p2c,fileno(stdin)); // Redirect standard input(0) to child 'read pipe'
dup2(fd_c2p,fileno(stdout)); // Redirect standard output(1) to child 'write pipe'
close(fd_p2c);
close(fd_c2p);
int ret = execl("/disk/sources/pipe_test/pipe_child","pipe_child",NULL);
fprintf(stderr,"External process failed, return code: %d...\n", ret);
kill( getppid(), 9 ); // Kill parent process
exit(-1);
}
else { // Parent process
fd_p2c = open( filename_p2c.c_str(), O_WRONLY );
if( fd_p2c < 0 ) {
fprintf(stderr,"Parent: Error opening the named pipe: %d %d '%s'\n", fd_p2c, errno, strerror(errno));
exit(-1);
}
file_c2p = fopen( filename_c2p.c_str(), "r");
fd_c2p = fileno( file_c2p );
if( fd_c2p < 0 ) {
fprintf(stderr,"Parent: Error opening the named pipe: %d %d '%s'\n", fd_c2p, errno, strerror(errno));
exit(-1);
}
}
int numElements = 10000;
int sizeBuffer = numElements * sizeof(float);
float* bufferIn = new float[numElements];
float* bufferOut = new float[numElements];
for( int i = 0; i < numElements; i++ ) {
bufferIn[i] = 0.0;
}
int numIterations = 5;
int numBytesAll = numElements * sizeof(float) * numIterations;
pthread_t thread;
threadStruct* threadParam = new threadStruct();
threadParam->file_c2p = file_c2p;
threadParam->sizeBuffer = sizeBuffer;
threadParam->buffer = bufferIn;
threadParam->io_flag = READING;
int thread_stat = pthread_create( &thread, NULL, threadFunction, threadParam );
if( thread_stat < 0 ) {
fprintf(stderr,"Error when creating thread\n");
exit(-1);
}
int readCounter = 0;
int numBytesWrite = 0;
int numBytesRead = 0;
for( int iter = 0; iter < numIterations; iter++ ) {
for( int i = 0; i < numElements; i++ ) {
bufferOut[i] = (float)i + iter*numElements*10;
}
int sizeWrite = (int)write( fd_p2c, bufferOut, sizeBuffer );
if( sizeWrite == -1 ) {
fprintf(stderr,"Parent process write error\n");
exit(-1);
}
numBytesWrite += sizeWrite;
fprintf(file_dump,"Parent #%d: Wrote %d/%d bytes.\n", iter, numBytesWrite, numBytesAll);
if( iter == numIterations-1 ) close(fd_p2c); // Closing output pipe makes sure child receives EOF
if( threadParam->io_flag != READING ) {
numBytesRead += sizeBuffer;
fprintf(file_dump,"Parent #%d: Read %d/%d bytes. Examples: %f %f\n",
readCounter, numBytesRead, numBytesAll, bufferIn[1], bufferIn[numElements-1] );
readCounter += 1;
if( threadParam->io_flag != FINISHED ) threadParam->io_flag = READING;
}
}
//********************************************************************************
//
fprintf(file_dump,"------------------------------\n");
while( threadParam->io_flag != FINISHED ) {
if( threadParam->io_flag == BUFFER_READY ) {
numBytesRead += sizeBuffer;
fprintf(file_dump,"Parent #%d: Read %d/%d bytes. Examples: %f %f\n",
readCounter, numBytesRead, numBytesAll, bufferIn[1], bufferIn[numElements-1] );
readCounter += 1;
if( threadParam->io_flag != FINISHED ) threadParam->io_flag = READING;
}
else {
mini_sleep(10);
}
}
// wait for thread to finish before continuing
pthread_join( thread, NULL );
fclose(file_dump);
fclose(file_c2p);
waitpid(pid, &status, 0); // clean up any children
fprintf(stderr,"..finished\n");
delete [] bufferIn;
delete [] bufferOut;
return 0;
}
Child program B:
#include <cstdio>
using namespace std;
int main() {
int numElements = 10000;
int totalSize = numElements * sizeof(float);
float* buffer = new float[numElements];
FILE* file_dump = fopen("child_dump","w");
int counter = 0;
int sizeRead = 0;
do {
sizeRead = fread( buffer, 1, totalSize, stdin);
if( sizeRead > 0 ) {
fprintf(file_dump,"Child #%d: Read %d bytes, examples: %f %f\n", counter, sizeRead, buffer[1], buffer[numElements-1]);
for( int i = 0; i < numElements; i++ ) {
buffer[i] += numElements;
}
int sizeWrite = fwrite( buffer, 1, totalSize, stdout);
fprintf(file_dump,"Child #%d: Wrote %d bytes, examples: %f %f\n", counter, sizeRead, buffer[1], buffer[numElements-1]);
counter += 1;
}
} while( sizeRead > 0 );
fprintf(file_dump,"Child is finished\n");
fclose(file_dump);
fclose(stdout);
return 0;
}