Blog Archive

Sunday, June 30, 2019

Dynamic memory access only works inside function & function(void **)

source: https://stackoverflow.com/questions/39486797/dynamic-memory-access-only-works-inside-function

This question is meant to be used as a canonical duplicate for this FAQ:
I am allocating data dynamically inside a function and everything works well, but only inside the function where the allocation takes place. When I attempt to use the same data outside the function, I get crashes or other unexpected program behavior.
Here is a MCVE:
#include <stdlib.h>
#include <stdio.h>

void create_array (int* data, int size)
{
  data = malloc(sizeof(*data) * size);
  for(int i=0; i<size; i++)
  {
    data[i] = i;
  }

  print_array(data, size);
}

void print_array (int* data, int size)
{
  for(int i=0; i<size; i++)
  {
    printf("%d ", data[i]);
  }
  printf("\n");
}

int main (void)
{
  int* data;
  const int size = 5;

  create_array(data, size);
  print_array(data, size);  // crash here

  free(data);
}
Whenever print_array is called from inside the create_array function, I get the expected output 0 1 2 3 4, but when I call it from main, I get a program crash.
What is the reason for this?

Asrman's notes: I corrected the syntax errors to make it successfully compiled.
#include <stdlib.h>
#include <stdio.h>
void print_array (int* data, int size)
{
  for(int i=0; i<size; i++)
  {
    printf("%d ", data[i]);
  }
  printf("\n");
}
void create_array (int* data, int size)
{
  //data = malloc(sizeof(*data) * size);
  data = (int *) malloc(sizeof(*data) * size);
  for(int i=0; i<size; i++)
  {
    data[i] = i;
  }

  print_array(data, size);
}
int main (void)
{
  int* data;
  const int size = 5;

  create_array(data, size);
  print_array(data, size);  // crash here

  free(data);
}
Answer:
The reason for this bug is that the data used by the create_array function is a local variable that only exists inside that function. The assigned memory address obtained from malloc is only stored in this local variable and never returned to the caller.

Consider this simple example:
void func (int x){
  x = 1;
  printf("%d", x);
}

...
int a;
func(a);
printf("%d", a); // bad, undefined behavior - the program might crash or print garbage
Here, a copy of the variable a is stored locally inside the function, as the parameter x. This is known as pass-by-value.
When x is modified, only that local variable gets changed. The variable a in the caller remains unchanged, and since a is not initialized, it will contain "garbage" and cannot be reliably used.

Pointers are no exception to this pass-by-value rule. In your example, the pointer variable data is passed by value to the function. The data pointer inside the function is a local copy and the assigned address from malloc is never passed back to the caller.
So the pointer variable in the caller remains uninitialized and therefore the program crashes. In addition, the create_array function has also created a memory leak, since after that function execution, there is no longer any pointer in the program keeping track of that chunk of allocated memory.

There are two ways you can modify the function to work as expected. Either by returning a copy of the local variable back to the caller:
int* create_array (int size)
{
  int* data = malloc(sizeof(*data) * size);
  for(int i=0; i<size; i++)
  {
    data[i] = i;
  }

  print_array(data, size);

  return data;
}

int main (void)
{
  int* data;
  const int size = 5;

  data = create_array(size);
  print_array(data, size);
}
or by passing the address to the caller's pointer variable and write directly to the caller variable:
void create_array (int** data, int size){
  int* tmp = (int *) malloc(sizeof(*tmp) * size);
  for(int i=0; i<size; i++)
    tmp[i] = i;  

  *data = tmp;      
  print_array(*data, size);
}

int main (void){
  int* data;
  const int size = 5;

  create_array(&data, size);
  print_array(data, size);
}
Either form is fine.
Another simple example:

void GetMemory2(char **p,int num){
   * p=malloc(sizeof(int)*num);
   return;
}

void Test2(){
      char *p=NULL;
     GetMemory2(&p);
}

Thursday, June 13, 2019

how to download voxceleb data automatically and prepare for kaldi experiment

Part 1: folder structure preparation:
suppose voxceleb 1 & 2 need to be downloaded into: voxceleb1 & voxceleb2
create dev, test under each directory and put all dev files into dev, test into test
i.e, the final folder directory should be:
mkdir -p voxceleb1/dev voxceleb1/test
mkdir -p voxceleb2/dev voxceleb2/test


Part 2: data download
wget --user=XX --password=YY http://www.robots.ox.ac.uk/~vgg/data/voxceleb/vox1a/vox2_test_aac.zip

You can follow the above example on both voxceleb1 and voxceleb2
Note you need fill this form to request a password.

https://github.com/kaldi-asr/kaldi/tree/master/egs/voxceleb/v1


Reference:
http://www.robots.ox.ac.uk/~vgg/data/voxceleb/vox1.html
http://www.robots.ox.ac.uk/~vgg/data/voxceleb/vox2.html
https://askubuntu.com/questions/29079/how-do-i-provide-a-username-and-password-to-wget

Sunday, May 26, 2019

How to setup & visit home server from outside

Date: 5/26/2019

Abstract:
This essay will focus on visiting home linux server from outside.
Step 1:
Go to the following website to register an account
https://www.noip.com/
For example:
username: YourOwnAccount@gmail.com
password: YourOwnPassword

Step 2: In your server, Download client & install & configure
Download the linux version of the noip client from the following link:
https://www.noip.com/download?page=linux


Once you have opened your Terminal window, log in as the “root” user. You can become the root user from the command line by entering “sudo -s” followed by the root password on your machine.
  1. cd /usr/local/src/
  2. wget http://www.no-ip.com/client/linux/noip-duc-linux.tar.gz
  3. tar xf noip-duc-linux.tar.gz
  4. cd noip-2.1.9-1/
  5. make install
  6. /usr/local/bin/noip2 -C (dash capital C, this will create the default config file)
  7. /usr/local/bin/noip2  & # run noip2 in backgroud


Ref:

https://www.noip.com/support/knowledgebase/installing-the-linux-dynamic-update-client-on-ubuntu/

Step 3: install ssh in your server
sudo apt-get update  # in case you have any problem, reboot system and re-run this
sudo apt-get install openssh-server
sudo service ssh status
http://ubuntuhandbook.org/index.php/2016/04/enable-ssh-ubuntu-16-04-lts/
Step 4: port forwarding:
Suppose you get you domain name from noip.com like the following:

http://YouOwnDDNSaccount.ddns.net/
Then you can setup port forwarding in the following
http://YouOwnDDNSaccount.ddns.net/port_forwarding.php
you can also try:
http://192.168.10.1/
the default
user:admin
pass:password

Step 5: Check:
Option 1:you can validate step3 with local ip of your server:
for example: (port: 22)
ssh yourUserName@10.0.0.136

Option 2:
try port 22 and ip: 12.34.56.78 (just for example)
https://www.yougetsignal.com/tools/open-ports/

Option 3: testing outside your home network (outside your home wifi)
ssh yourUserName@12.34.56.78
Note, you can not test option 3 within your home network.

Refererece:
1) https://www.howtogeek.com/66438/how-to-easily-access-your-home-network-from-anywhere-with-ddns/
2) hardware: arris router
ARRIS Surfboard (24x8) DOCSIS 3.0 Cable Modem Plus AC1750 Dual Band Wi-Fi Router and Xfinity Telephone, 1 Gbps Max Speed, Certified for Comcast Xfinity Only (SVG2482AC)
https://www.amazon.com/gp/product/B06XDGWKSB/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1

Wednesday, April 10, 2019

[how to remember] priority_queue vs sort



https://coliru.stacked-crooked.com/view?id=27147c4921124ec6

http://www.cplusplus.com/reference/algorithm/sort/

#include <functional>
#include <queue>
#include <vector>
#include <iostream>
bool myfunction (int left, int right) { return (left ) < (right);}
//auto cmp = [](int left, int right) { return left < right;};
auto cmp = [](int  left, int head) { return left < head;}; 
// head is 1st come out of priority_queue; left is what is left
template<typename T> void print_queue(T& q) {
    while(!q.empty()) {
        std::cout << q.top() << " ";
        q.pop();
    }
    std::cout << '\n';
}

int main() {
    std::priority_queue<int> q;

    for(int n : {1,8,5,6,3,4,0,9,7,2})
        q.push(n);

    print_queue(q);

    std::priority_queue<int, std::vector<int>, std::greater<int> > q2;

    for(int n : {1,8,5,6,3,4,0,9,7,2})
        q2.push(n);

    print_queue(q2);

    // Using lambda to compare elements.
    //auto cmp = [](int left, int right) { return (left ^ 1) < (right ^ 1);};
    //auto cmp = [](int left, int right) { return (left ) < (right);};

    std::priority_queue<int, std::vector<int>, decltype(cmp)> q3(cmp);

    for(int n : {1,8,5,6,3,4,0,9,7,2})
        q3.push(n);

    print_queue(q3);
    std::vector<int> ivec({1,8,5,6,3,4,0,9,7,2});
   
    sort(ivec.begin(), ivec.end(), myfunction);
    for(std::vector<int>::iterator it=ivec.begin(); it!=ivec.end(); it++){
       std::cout<<*it<<" ";
    }
    std::cout<<std::endl;

}

g++ -std=c++2a -pthread -fgnu-tm  -O2 -Wall -Wextra -pedantic -pthread -pedantic-errors main.cpp -lm  -latomic -lstdc++fs  && ./a.out
9 8 7 6 5 4 3 2 1 0 
0 1 2 3 4 5 6 7 8 9 
9 8 7 6 5 4 3 2 1 0 
0 1 2 3 4 5 6 7 8 9 

Tuesday, March 5, 2019

How to write a bash script that takes optional input arguments?


ref: 


You can set a default value for a variable like so:

somecommand.sh

#!/usr/bin/env bash

ARG1=${1:-foo}
ARG2=${2:-bar}
ARG3=${3:-1}
ARG4=${4:-$(date)}

echo "$ARG1"
echo "$ARG2"
echo "$ARG3"
echo "$ARG4"
Here are some examples of how this works:
$ ./somecommand.sh
foo
bar
1
Thu Mar 29 10:03:20 ADT 2018

$ ./somecommand.sh ez
ez
bar
1
Thu Mar 29 10:03:40 ADT 2018

$ ./somecommand.sh able was i
able
was
i
Thu Mar 29 10:03:54 ADT 2018

$ ./somecommand.sh "able was i"
able was i
bar
1
Thu Mar 29 10:04:01 ADT 2018

$ ./somecommand.sh "able was i" super
able was i
super
1
Thu Mar 29 10:04:10 ADT 2018

$ ./somecommand.sh "" "super duper"
foo
super duper
1
Thu Mar 29 10:05:04 ADT 2018

$ ./somecommand.sh "" "super duper" hi you
foo
super duper
hi
you